home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / gfx / edit / TSMrph23s.lha / TSM23s.lha / TSMorph-render.c < prev    next >
C/C++ Source or Header  |  1993-10-08  |  90KB  |  2,877 lines

  1. // TSMorph - Amiga Morphing program
  2. // Copyright (C) © 1993  Topicsave Limited
  3.  
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // any later version.
  8.  
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13.  
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. // mpaddock@cix.compulink.co.uk
  19.  
  20. //    $Author: M_J_Paddock $
  21. //    $Date: 1993/09/11 21:55:48 $
  22. //    $Revision: 1.16 $
  23.  
  24. /* Amiga headers */
  25. #define INTUI_V36_NAMES_ONLY
  26. #define INTUITION_IOBSOLETE_H
  27.  
  28. // Include correct math library
  29. #ifdef MY68881
  30. #include <m68881.h>
  31. #else
  32. #include <math.h>
  33. #endif
  34.  
  35. // prevent inclusion of another math library
  36. #define LIBRARIES_MATHFFP_H
  37.  
  38. // other headers, define some non 2.02 header stuff
  39. #include <exec/types.h>
  40. #include <exec/memory.h>
  41. #include <intuition/intuition.h>
  42. #include <intuition/gadgetclass.h>
  43. #ifndef PGA_NewLook
  44. #define PGA_NewLook (PGA_Dummy + 0x000A)
  45. #endif
  46. #include <intuition/imageclass.h>
  47. #include <intuition/icclass.h>
  48. #include <devices/input.h>
  49. #include <workbench/workbench.h>
  50. #include <workbench/startup.h>
  51. #include <libraries/gadtools.h>
  52. #ifndef GTMN_FullMenu
  53. #define GTMN_FullMenu GT_TagBase+62
  54. #endif
  55. #include <libraries/asl.h>
  56.  
  57. #include <clib/exec_protos.h>
  58. #include <clib/dos_protos.h>
  59. #include <clib/layers_protos.h>
  60. #include <clib/graphics_protos.h>
  61. #include <clib/intuition_protos.h>
  62. #include <clib/input_protos.h>
  63. #include <clib/gadtools_protos.h>
  64. #include <clib/asl_protos.h>
  65. #include <clib/utility_protos.h>
  66.  
  67. #include <pragmas/exec_pragmas.h>
  68. #include <pragmas/dos_pragmas.h>
  69. #include <pragmas/layers_pragmas.h>
  70. #include <pragmas/graphics_pragmas.h>
  71. #include <pragmas/intuition_pragmas.h>
  72. #include <pragmas/input_pragmas.h>
  73. #include <pragmas/gadtools_pragmas.h>
  74. #include <pragmas/asl_pragmas.h>
  75. #include <pragmas/utility_pragmas.h>
  76.  
  77. #include <proto/diskfont.h>
  78. #include <proto/icon.h>
  79.  
  80. #include <devices/timer.h>
  81.  
  82. #include <clib/timer_protos.h>
  83. #include <pragmas/timer_pragmas.h>
  84.  
  85. #include <clib/alib_protos.h>
  86.  
  87. #include <rexx/errors.h>
  88. #include <pragmas/rexxsyslib_pragmas.h>
  89. #include <clib/rexxsyslib_protos.h>
  90.  
  91. #include <libraries/amigaguide.h>
  92. #include <clib/amigaguide_protos.h>
  93. #include <pragmas/amigaguide_pragmas.h>
  94.  
  95. #include <libraries/reqtools.h>
  96. #include <clib/reqtools_protos.h>
  97. #include <pragmas/reqtools.h>
  98.  
  99. #include <opal/opallib.h>
  100.  
  101. #include <libraries/dctv.h>
  102. #include <clib/dctv_protos.h>
  103. #include <pragmas/dctv_pragmas.h>
  104.  
  105. #include <stddef.h>
  106. #include <string.h>
  107. #include <stdio.h>
  108. #include <stdlib.h>
  109.  
  110. /* Below is not in the 2.02 version of clib/utility_protos.h
  111.                                        pragmas/utility_pragmas.h */
  112. #if INCLUDE_VERSION < 37
  113. LONG Stricmp(UBYTE *string1,UBYTE *string2);
  114. #pragma libcall UtilityBase Stricmp A2 9802
  115. #endif
  116.  
  117. // IFF header
  118. #include "iffp/ILBMapp.h"
  119.  
  120. // Progress requester
  121. #include "progress.h"
  122.  
  123. // JPEG load stuff
  124. #include "JPEG_LS/jinclude.h"
  125.  
  126. // Help nodes
  127. STRPTR context[] = {
  128.     "",
  129.     "Main",
  130.     "Err-IFFBMHD",
  131.     "Err-IFFRaster",
  132.     "Err-IFFBODY",
  133.     "Err-IFFCLIP",
  134.     "Err-IFFILBM",
  135.     "Err-IFFFileS",
  136.     "Err-IFFTop",
  137.     "Err-IFFMemory",
  138.     "Req-Progress",
  139.     "Err-LibraryR",
  140.     "Err-Saving",
  141.     "Err-AllocVec",
  142.     "Err-OpenPoints",
  143.     "Err-Progress",
  144.     "Err-AllocPlanes",
  145.     "Err-24",
  146.     "Err-Load",
  147.     "Err-AllocIFF",
  148.     "Err-AllocILBM",
  149.     "Err-FileFormat",
  150.     "Err-SizeMatch",
  151.     "Err-Range",
  152.     "Err-MemPointsR",
  153.     "Err-CloseFile",
  154.     "Err-3Points",
  155.     "Err-OpenFile",
  156.     "Err-ARexx",
  157.     "Req-Really_quit",
  158.     "Err-OldFormat",
  159.     "Err-OpalVision",
  160.     "Err-NoOpal",
  161. };
  162.  
  163. #define H_Help         10
  164. #define H_Library        11
  165. #define H_ESave        12
  166. #define H_AllocVec    13
  167. #define H_OpenPoints    14
  168. #define H_Progress    15
  169. #define H_AllocPlanes 16
  170. #define H_24            17
  171. #define H_Load            18
  172. #define H_AllocIFF    19
  173. #define H_AllocILBM    20
  174. #define H_FileFormat    21
  175. #define H_SizeMatch    22
  176. #define H_Range        23
  177. #define H_MemPointsR    24
  178. #define H_CloseFile    25
  179. #define H_3Points        26
  180. #define H_Open            27
  181. #define H_ARexx        28
  182. #define H_Really        29
  183. #define HE_OldFormat    30
  184. #define HE_OpalVision 31
  185. #define HE_NoOpal        32
  186.  
  187. // Disable Ctrl-C checking
  188. int CXBRK(void) { return(0); }
  189. int chkabort(void) { return(0); }
  190.  
  191. // Libraries
  192. extern struct Library *SysBase;
  193. extern struct DOSBase *DOSBase;
  194. struct Library *IntuitionBase, *GfxBase, *LayersBase, *IFFParseBase;
  195. struct Library *GadToolsBase, *AslBase, *UtilityBase;
  196. struct Library *RexxSysBase;
  197. struct Library *AmigaGuideBase;
  198. struct Library *TimerBase=NULL;
  199. struct Library *ReqToolsBase;
  200. struct Library *DCTVBase;
  201.  
  202. struct OpalBase *OpalBase = NULL;
  203.  
  204. extern struct List InfoList; // List of messages
  205.  
  206. // Help stuff
  207. AMIGAGUIDECONTEXT handle;
  208. struct NewAmigaGuide nag = {NULL};
  209. ULONG ASig = 0;
  210.  
  211. /* Version string for CLI version */
  212. #ifdef MY68881
  213. char *Version = "$VER: TSMorph-render_881 2.3 (6.10.93)";
  214. #else
  215. char *Version = "$VER: TSMorph-render 2.3 (6.10.93)";
  216. #endif
  217.  
  218. BOOL Pic1_Open = FALSE;                // 1st image open OK
  219. BOOL Pic2_Open = FALSE;                // 2nd image open OK
  220.  
  221. struct MsgPort        *WMsgPortp;        // Message port for Picture Windows
  222.  
  223. // Properties for IFF read
  224. LONG props[] = {    ID_ILBM,    ID_BMHD,
  225.                         ID_ILBM,    ID_CAMG,
  226.                         ID_ILBM, ID_CMAP,
  227.                         TAG_DONE };
  228. LONG stops[] = {    ID_ILBM,    ID_BODY,
  229.                         TAG_DONE };
  230. LONG nowt[] = { TAG_DONE };
  231.  
  232. /* Wait pointer */
  233. static USHORT __chip BusyPointerData[] =
  234. {
  235.    0x0000,0x0000,
  236.    0x0400,0x07C0,0x0000,0x07C0,0x0100,0x0380,0x0000,0x07E0,
  237.    0x07C0,0x1FF8,0x1FF0,0x3FEC,0x3FF8,0x7FDE,0x3FF8,0x7FBE,
  238.    0x7FFC,0xFF7F,0x7EFC,0xFFFF,0x7FFC,0xFFFF,0x3FF8,0x7FFE,
  239.    0x3FF8,0x7FFE,0x1FF0,0x3FFC,0x07C0,0x1FF8,0x0000,0x07E0,
  240.    0x0000,0x0000,
  241. };
  242.  
  243. // Protos
  244. BOOL SaveFile(void);
  245. BOOL Load24bit(char *filename,struct Picture *pic,BOOL GUI);
  246. void Close24bit(struct Picture *pic);
  247. void Error(char *ErrorMessage, char *Gadget,char *extra,ULONG hnum);
  248. void DeleteAllPoints(void);
  249. void __regargs FindPoint(struct MyPoint *RetPoint);
  250. BOOL MyOpen(char *filename,BOOL JustPoints);
  251. UWORD __regargs intersect(struct MyPoint *Pointa,struct MyPoint *Pointb);
  252. void __regargs CalcDiffs(struct MyPoint *a,struct MyPoint *bb,double *ab1,double *ab2,double *ab);
  253. void __regargs Triangle(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c);
  254. void __regargs checktriangle(struct MyPoint *,struct MyPoint *,struct MyPoint *,struct MyPoint **,struct MyPoint **,struct MyPoint **,ULONG *,UWORD *);
  255. LONG SendRxMsg(char *msgtxt,BOOL IgnoreError);
  256. extern void MyArgArrayInit(int argc,char **argv);
  257. extern void MyArgArrayDone(void);
  258. extern UBYTE *MyArgString(UBYTE *arg2,UBYTE *arg3,BOOL reopen);
  259. extern LONG MyArgInt(UBYTE *arg2, long arg3,BOOL reopen);
  260. extern BOOL MyFindToolType(UBYTE *arg2,BOOL reopen);
  261. void OpenNewArgs(UBYTE *filename);
  262. void DisableWindow(void);
  263. void EnableWindow(void);
  264. void help(ULONG hnum);
  265. BOOL LoadFrames(BOOL points,BOOL image1,BOOL image2);
  266. void AddMessage(UBYTE *message);
  267.  
  268. // Args.c
  269. void argArrayDone( void );
  270. char **argArrayInit( LONG argc, char **argv );
  271.  
  272. // SaveHAMetc.c
  273. BOOL SaveBW16(UBYTE *FileName,USHORT width,USHORT height, UWORD swidth,
  274.                   USHORT pwidth, USHORT pheight, USHORT pmode,
  275.                   UBYTE *red, UBYTE *green, UBYTE *blue, struct RastPort *rp, struct RastPort *trp);
  276. BOOL SaveBW256(UBYTE *FileName,USHORT width,USHORT height, UWORD swidth,
  277.                   USHORT pwidth, USHORT pheight, USHORT pmode,
  278.                   UBYTE *red, UBYTE *green, UBYTE *blue, struct RastPort *rp, struct RastPort *trp);
  279. BOOL SaveHAM6(UBYTE *FileName,USHORT width,USHORT height, UWORD swidth,
  280.                   USHORT pwidth, USHORT pheight, USHORT pmode,
  281.                   UBYTE *red, UBYTE *green, UBYTE *blue, struct RastPort *rp, struct RastPort *trp);
  282. BOOL SaveHAM8(UBYTE *FileName,USHORT width,USHORT height, UWORD swidth,
  283.                   USHORT pwidth, USHORT pheight, USHORT pmode,
  284.                   UBYTE *red, UBYTE *green, UBYTE *blue, struct RastPort *rp, struct RastPort *trp);
  285. BOOL SaveDCTV(UBYTE *FileName,USHORT width,USHORT height, UWORD swidth,
  286.                   USHORT pwidth, USHORT pheight, USHORT pmode,
  287.                   UBYTE *red, UBYTE *green, UBYTE *blue, struct RastPort *rp, struct RastPort *trp);
  288.  
  289. // some work buffers
  290. char buffer[256]="";
  291. char buffer1[512]="";
  292.  
  293. // Image structure
  294. struct Picture {
  295.     struct ILBMInfo    *ilbm;        // For IFF read
  296.     UBYTE                    *red;            // Read chunky pixels    Must be RGB for Opal OVtoRGB
  297.     UBYTE                    *green;        // Green
  298.     UBYTE                    *blue;        // Blue
  299.     UBYTE                    filename[256];    // filename
  300.     struct OpalScreen *OScrn;        // OpalScreen
  301.     BOOL                    rgbonelot;    // Is red,green,blue one AllocVec
  302. };
  303.  
  304. struct Picture Pic1={0},Pic2={0};// 1st and 2nd image
  305.  
  306. UBYTE *plane0=NULL;                    // Planes for temporary bit maps
  307. UBYTE *plane1=NULL;
  308. UBYTE *plane2=NULL;
  309. UBYTE *plane3=NULL;
  310. UBYTE *plane4=NULL;
  311. UBYTE *plane5=NULL;
  312. UBYTE *plane6=NULL;
  313. UBYTE *plane7=NULL;
  314.  
  315. // Point structure
  316. struct MyPoint {
  317.     struct MinNode MyNode;    // linked into list
  318.     WORD x,y;        // Coordinates in 1st image
  319.     WORD x1,y1;        // 2nd image
  320.     WORD Cx,Cy;        // Current image
  321.     LONG Cdiff;        // seperation between two points (squared)
  322.     WORD xdiff;        // x difference
  323.     WORD ydiff;        // y difference
  324.     double xd,yd;    // double coords for AntiAlias
  325.     double x1d,y1d;// 2nd image
  326. };
  327.  
  328. // 24 bitplane bitmap
  329. struct MyBitMap {
  330.     struct BitMap BitMap;
  331.     PLANEPTR xplanes[16];
  332. };
  333.  
  334. // List of points
  335. struct List            PointList;
  336.  
  337. // Size of image
  338. USHORT    width, height, pwidth, pheight, pmode;
  339.  
  340. char AnimName[256];    // Buffer for file name to save
  341.  
  342. char *Loadscript;        // ARexx load script
  343.  
  344. WORD x,y;                // Current coords
  345.  
  346. struct MyPoint **Points = NULL;    // Pointer to points
  347.  
  348. UWORD    Depth;    // Number of points to check each time
  349.  
  350. UWORD Mode;        // Mode = 0 use 3 closest if no others, choose 1st 3
  351.                     // Mode = 1 leave points stationary, choose 1st 3
  352.                     // Mode = 2 choose 3 closet, always use
  353.                     // Mode = 3 leave points stationary, choose 3 closest
  354.  
  355. #define MODE_STAT        1
  356. #define MODE_CLOSEST    2
  357.  
  358. LONG PointCount = 0;            // Number of points
  359.  
  360. struct MyPoint BigPoint;    // Point far away
  361.  
  362. char MyFileName[257];
  363.  
  364. // Settings stuff
  365. char **ArgArray;
  366. char **ArgArraySettings;
  367.  
  368. // OpalVision screen
  369. struct OpalScreen *OScrn = NULL;
  370.  
  371. char                 *OVFormat;    // Format of OpalVision save JPG or IFF (or anything) default
  372. BOOL                AntiAlias;    // AntiAlias points
  373.  
  374. // Table of parameters
  375. struct {
  376.     LONG xf;                // Current frame
  377.     LONG xFrames;        // Number of frames
  378.     LONG xSingle;        // Warp or Morph
  379.     LONG xmove;            // Movement 1 to 2
  380.     LONG xr;                // red of image 1
  381.     LONG xg;                // green
  382.     LONG xb;                // blue
  383.     LONG xr2;            // red of image 2
  384.     LONG xg2;            // green
  385.     LONG xb2;            // blue
  386.     LONG xDo;            // Produce this image
  387.     LONG xrplus;        // Add red
  388.     LONG xgplus;        // green
  389.     LONG xbplus;        // blue
  390.     LONG xrminus;        // subtract red
  391.     LONG xgminus;        // subtract green
  392.     LONG xbminus;        // subtract blue
  393.     LONG xDX;            // X skip
  394.     LONG xDY;            // Y skip
  395.     LONG xStart;        // Start Frame number
  396.     LONG FILLER[32];    // Filler for future expansion
  397. } Arexx;
  398.  
  399. #define f Arexx.xf
  400. #define Frames Arexx.xFrames
  401. #define Single Arexx.xSingle
  402. #define move Arexx.xmove
  403. #define r Arexx.xr
  404. #define g Arexx.xg
  405. #define b Arexx.xb
  406. #define r2 Arexx.xr2
  407. #define g2 Arexx.xg2
  408. #define b2 Arexx.xb2
  409. #define Do Arexx.xDo
  410. #define rplus Arexx.xrplus
  411. #define gplus Arexx.xgplus
  412. #define bplus Arexx.xbplus
  413. #define rminus Arexx.xrminus
  414. #define gminus Arexx.xgminus
  415. #define bminus Arexx.xbminus
  416. #define DX Arexx.xDX
  417. #define DY Arexx.xDY
  418. #define Start Arexx.xStart
  419.  
  420. // Display help if available
  421. void
  422. help(ULONG hnum) {
  423.     if (handle) {
  424.         SetAmigaGuideContext(handle,hnum,NULL);
  425.         SendAmigaGuideContext(handle,NULL);
  426.     }
  427. }
  428.  
  429. char                     FileName[256];    // File name buffer
  430. long                    OVQuality;    // OpalVision JPG quality
  431. BOOL                    OVFast;        // OpalVision fast format IFF
  432. BOOL                    OVThumb;        // OpalVision Thumbail
  433. BOOL                    HAM6;
  434. BOOL                    HAM8;
  435. BOOL                    BW16;
  436. BOOL                    BW256;
  437. BOOL                    DCTV3 = FALSE;
  438. BOOL                    DCTV4 = FALSE;
  439. UBYTE                 *arrayr,        // Pointers to red,green and blue
  440.                          *arrayg,
  441.                          *arrayb;
  442. BOOL                    PPM;            // PPM save ?
  443. UBYTE        *p[3] = {NULL,NULL,NULL};// chunky pointers - order for OpalVision
  444. #define RED p[0]
  445. #define BLUE p[2]
  446. #define GREEN p[1]
  447. UWORD        swidth;        // scaled width (in full words)
  448. struct RastPort     RP,            // Work Rast Ports
  449.                          TRP;
  450. struct MyBitMap     MyBitMap;    // Real bit map
  451. PLANEPTR             Planes[24] = {NULL};    // Bit planes
  452. BOOL                    CreateIcons;// Create Icons on pictures?
  453. char                     *Postscript;// ARexx postscript
  454.  
  455. /* Main program    */
  456. void
  457. main(int argc,char **argv) {
  458.  BOOL     OkFlag    = TRUE;    // Is it working ?
  459.  char     *e            = NULL;    // error message
  460.  struct MyPoint     MyPoint;        // Points to work with
  461.  struct MyPoint     *MyPointp;
  462.  BOOL                 Opened;        // has file been opened
  463.  struct WBStartup *argmsg;        // Workbench stuff
  464.  struct WBArg         *wb_arg;
  465.  char                 *e1;            // The rest of the error message
  466.  struct Window     *oldWindowPtr;    // Redirect the system requesters
  467.  struct Process     *process;
  468.  char                 *filename;    // file name
  469.  ULONG                 offset,        // 2d to 1d array offsets
  470.                          offset1;
  471.  char                 *Prescript;    // Rexx script names
  472.  UWORD                myx,            // indexes for skipping
  473.                          myy;
  474.  UBYTE                xr,            // more skipping stuff
  475.                          xg,
  476.                          xb;
  477.  struct AmigaGuideMsg *agm;    // help stuff
  478.  struct timeval    time1,        // To display time per image
  479.                          time2;
  480.  struct timerequest tr;
  481.  BOOL                 t2    = FALSE;    // Set when the times calculated
  482.  char                 tbuffer[30];// buffer for time message
  483.  ULONG                hnum = 0;    // Help number for error
  484.  BOOL                    Alloced=FALSE;    // Allocated memory?
  485.  char                    *Tstr;        // Temp string for parameter
  486.  UWORD                xbig;
  487.  double                xsmall;        // Int and rest of coords
  488.  UWORD                ybig;
  489.  double                ysmall;        // y coords
  490.  WORD                    right,down;    // move right and down?
  491.  UWORD                xbig1;
  492.  double                xsmall1;        // Int and rest of coords
  493.  UWORD                ybig1;
  494.  double                ysmall1;        // y coords
  495.  WORD                    right1,down1;// move right and down?
  496.  double                a,bb,c,d,a1,b1,c1,d1;    // AntiAlias stuff
  497.  
  498.  // Set up BigPoint
  499.  BigPoint.Cdiff = 0x7FFFFFFF;
  500.  // Initialise points list
  501.  NewList(&PointList);
  502.  // Try and open reqtools.library and dctv.library
  503.  ReqToolsBase = OpenLibrary("reqtools.library",38);
  504.  DCTVBase = OpenLibrary("dctv.library",3);
  505.  // Set up amigaguide (if available)
  506.  if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 33L)) {
  507.   nag.nag_BaseName = "TSMorph";
  508.   nag.nag_Name = "TSMorph.guide";
  509.   nag.nag_ClientPort = "TSMorph-render_HELP";
  510.   nag.nag_Context = context;
  511.   if (handle = OpenAmigaGuideAsync (&nag, NULL)) {
  512.    ASig = AmigaGuideSignal(handle);
  513.   }
  514.  }
  515.  // Try and open the timer
  516.  if (!OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *) &tr, 0L)) {
  517.   TimerBase = (struct Library *)tr.tr_node.io_Device;
  518.  }
  519.  // Try and open OpalVision library
  520.  OpalBase = (struct OpalBase *)OpenLibrary("opal.library",0L);
  521.  // Open all the libraries
  522.  if (IntuitionBase = OpenLibrary("intuition.library",37L)) {
  523.   if (RexxSysBase = OpenLibrary("rexxsyslib.library",0)) {
  524.    if (IFFParseBase = OpenLibrary("iffparse.library",37L)) {
  525.     if (GfxBase = OpenLibrary("graphics.library",37L)) {
  526.      if (LayersBase = OpenLibrary("layers.library",37L)) {
  527.       if (GadToolsBase = OpenLibrary("gadtools.library",37L)) {
  528.        if (AslBase = OpenLibrary("asl.library",37L)) {
  529.         if (UtilityBase = OpenLibrary("utility.library",37)) {
  530.          if (IconBase = OpenLibrary("icon.library",37L)) {
  531.           if (DiskfontBase = OpenLibrary("diskfont.library",36)) {
  532.             // Read and process the parameters
  533.             MyArgArrayInit(argc,argv);
  534.             PubScreenName = MyArgString("PUBSCREENR",NULL,FALSE);
  535.             // Open the progress window
  536.                if ((!SetupScreen())  && (!OpenProgressWindow())) {
  537.                    // redirect requesters
  538.              process = (struct Process *)FindTask(NULL);
  539.              oldWindowPtr = process->pr_WindowPtr;
  540.              process->pr_WindowPtr = ProgressWnd;
  541.              // Open the project file (CLI or WB)
  542.              DisableWindow();
  543.                   AddMessage("Opening points file");
  544.              if (argc) {
  545.                 if (filename = ArgString(ArgArray,"FILES",NULL)) {
  546.                Opened = MyOpen(filename,FALSE);
  547.               }
  548.               else {
  549.                 Opened = MyOpen(NULL,FALSE);
  550.               }
  551.              }
  552.              else {
  553.               argmsg = (struct WBStartup *)argv;
  554.                  if (argmsg->sm_NumArgs > 1) {
  555.                 wb_arg = argmsg->sm_ArgList;
  556.                 wb_arg++;
  557.                 if (wb_arg->wa_Lock) {
  558.                   NameFromLock(wb_arg->wa_Lock,buffer,256);
  559.                  }
  560.                   if (AddPart(buffer,wb_arg->wa_Name,256)) {
  561.                    Opened = MyOpen(buffer,FALSE);
  562.                }
  563.               }
  564.               else {
  565.                   Opened = MyOpen(NULL,FALSE);
  566.                  }
  567.                 }
  568.                 if (Opened) {
  569.                  // Get a few parameters
  570.                  Tstr = MyArgString("SAVEFORMAT","ILBM24",FALSE);
  571.                  if (OpalBase) {
  572.                   if (MatchToolValue(Tstr,"OPAL24") || MatchToolValue(Tstr,"OPAL24T") ||
  573.                       MatchToolValue(Tstr,"OPAL24F") || MatchToolValue(Tstr,"OPAL24FT")) {
  574.                    OVFormat = "IFF";
  575.                   }
  576.                   else {
  577.                    if (MatchToolValue(Tstr,"JPEG") || MatchToolValue(Tstr,"JPEGT")) {
  578.                     OVFormat = "JPG";
  579.                    }
  580.                    else {
  581.                     OVFormat = NULL;
  582.                    }
  583.                   }
  584.                  }
  585.                  else {
  586.                   OVFormat = NULL;
  587.                  }
  588.                  PPM = MatchToolValue(Tstr,"PPM");
  589.                  HAM6 = MatchToolValue(Tstr,"HAM6");
  590.                  HAM8 = MatchToolValue(Tstr,"HAM8");
  591.                  BW16 = MatchToolValue(Tstr,"BW16");
  592.                  BW256 = MatchToolValue(Tstr,"BW256");
  593.                  if (DCTVBase) {
  594.                   DCTV3 = MatchToolValue(Tstr,"DCTV3");
  595.                   DCTV4 = MatchToolValue(Tstr,"DCTV4");
  596.                  }
  597.               OVQuality = MyArgInt("QUALITY",75,FALSE);
  598.               if (MatchToolValue(Tstr,"OPAL24T") || MatchToolValue(Tstr,"JPEGT")) {
  599.                OVThumb = TRUE;
  600.               }
  601.               else {
  602.                OVThumb = FALSE;
  603.               }
  604.               if (MatchToolValue(Tstr,"OPAL24F") || MatchToolValue(Tstr,"OPAL24FT")) {
  605.                OVFast = TRUE;
  606.               }
  607.               else {
  608.                OVFast = FALSE;
  609.               }
  610.               Prescript = MyArgString("PRESCRIPT","Rexx/Prescript",FALSE);
  611.               Postscript = MyArgString("POSTSCRIPT","Rexx/Postscript",FALSE);
  612.               Loadscript = MyArgString("LOADSCRIPT","Rexx/Loadscript",FALSE);
  613.               DX = MyArgInt("DX",0,FALSE);
  614.               DY = MyArgInt("DY",0,FALSE);
  615.               Depth = max(MyArgInt("DEPTH",2,FALSE),20);
  616.               Mode = MyArgInt("MODE",0,FALSE);
  617.               CreateIcons = MatchToolValue(MyArgString("CREATEICONSR","NO",FALSE),"YES");
  618.               AntiAlias = MatchToolValue(MyArgString("ANTIALIAS","NO",FALSE),"YES");
  619.                  // File has been opened, cache width in full words
  620.                  swidth = (((width+15)>>4)<<4);
  621.                    AddMessage("Allocating work memory");
  622.                    // Allocate chunky and ILBM bit maps
  623.                  if ((RED = AllocVec((swidth*height),0)) &&
  624.                          (GREEN = AllocVec((swidth*height),0)) &&
  625.                          (BLUE =  AllocVec((swidth*height),0)) &&
  626.                          ((OpalBase && OVFormat && !PPM && (OScrn = CreateScreen24(0,width,height))) ||
  627.                           PPM ||
  628.                           (!OVFormat && !PPM &&
  629.                           (Planes[0] = AllocRaster(width,height)) &&
  630.                           (Planes[1] = AllocRaster(width,height)) &&
  631.                           (Planes[2] = AllocRaster(width,height)) &&
  632.                           (DCTV3 ||
  633.                            ((Planes[3] = AllocRaster(width,height)) &&
  634.                            (DCTV4 || BW16 ||
  635.                             ((Planes[4] = AllocRaster(width,height)) &&
  636.                              (Planes[5] = AllocRaster(width,height)) &&
  637.                              (HAM6 ||
  638.                               ((Planes[6] = AllocRaster(width,height)) &&
  639.                                (Planes[7] = AllocRaster(width,height)) &&
  640.                                (HAM8 || BW256 ||
  641.                                 ((Planes[8] = AllocRaster(width,height)) &&
  642.                                  (Planes[9] = AllocRaster(width,height)) &&
  643.                                  (Planes[10] = AllocRaster(width,height)) &&
  644.                                  (Planes[11] = AllocRaster(width,height)) &&
  645.                                  (Planes[12] = AllocRaster(width,height)) &&
  646.                                  (Planes[13] = AllocRaster(width,height)) &&
  647.                                  (Planes[14] = AllocRaster(width,height)) &&
  648.                                  (Planes[15] = AllocRaster(width,height)) &&
  649.                                  (Planes[16] = AllocRaster(width,height)) &&
  650.                                  (Planes[17] = AllocRaster(width,height)) &&
  651.                                  (Planes[18] = AllocRaster(width,height)) &&
  652.                                  (Planes[19] = AllocRaster(width,height)) &&
  653.                                  (Planes[20] = AllocRaster(width,height)) &&
  654.                                  (Planes[21] = AllocRaster(width,height)) &&
  655.                                  (Planes[22] = AllocRaster(width,height)) &&
  656.                                  (Planes[23] = AllocRaster(width,height))))))))))))) { // Looks like LISP!!!!
  657.                      Alloced = TRUE;
  658.                      // Update the progress
  659.                     EnableWindow();
  660.                     GT_SetGadgetAttrs(ProgressGadgets[GDX_Frame],ProgressWnd,NULL,
  661.                                            GTSL_Min,1,
  662.                                           GTSL_Max,Frames,TAG_END);
  663.                     GT_SetGadgetAttrs(ProgressGadgets[GDX_Line],ProgressWnd,NULL,
  664.                                            GTSL_Min,0,
  665.                                           GTSL_Max,height-1,TAG_END);
  666.                    // Pass to ARexx for processing
  667.                     if (strcmp(Prescript,"OFF")) {
  668.                     AddMessage("Prescript for frame 0");
  669.                    f = 0;
  670.                    Do = 0;
  671.                      strcpy(buffer,Prescript);
  672.                      strcat(buffer," %ld");
  673.                      sprintf(buffer1,buffer,&Arexx);
  674.                      OkFlag = !SendRxMsg(buffer1,FALSE);
  675.                      if (!OkFlag) {
  676.                        e = (char *)-1;
  677.                      }
  678.                      if (Do && OkFlag) {
  679.                       OkFlag = LoadFrames(FALSE,TRUE,FALSE);
  680.                       if (!OkFlag) {
  681.                        e = (char *)-1;
  682.                       }
  683.                       else {
  684.                       AddMessage("Saving frame 0");
  685.                        memcpy(RED,Pic1.red,swidth*height);
  686.                        memcpy(GREEN,Pic1.green,swidth*height);
  687.                        memcpy(BLUE,Pic1.blue,swidth*height);
  688.                        OkFlag = SaveFile();
  689.                      if (!OkFlag) {
  690.                       e = (char *)-1;
  691.                      }
  692.                       }
  693.                      }
  694.                     }
  695.                     // Determine start time
  696.                     if (TimerBase) {
  697.                      GetSysTime(&time1);
  698.                     }
  699.                     // Loop thru frames
  700.                 for (f=1;
  701.                       (f < (Frames+1)) && OkFlag;        // no of Frames
  702.                         f++) {
  703.                      // Update progress
  704.                      AddMessage("Prescript processing");
  705.                    GT_SetGadgetAttrs(ProgressGadgets[GDX_Frame],ProgressWnd,NULL,
  706.                                             GTSL_Level,f,TAG_END);
  707.                    // calculate default image parameters
  708.                      rplus = gplus = bplus = rminus = gminus = bminus = 0;
  709.                      if ((Single == 1) || (Single == 3)) {
  710.                       move = ((Frames-f) << 10)/Frames;
  711.                       r = g = b = 1024;
  712.                       r2 = g2 = b2 = 0;
  713.                       Do = 1;
  714.                      }
  715.                      else {
  716.                       r = g = b = move = ((Frames-f+1) << 10)/(Frames + 1);
  717.                       r2 = g2 = b2 = (1024 - r);
  718.                       Do = 1;
  719.                      }
  720.                      // Pass to ARexx for processing
  721.                      if (strcmp(Prescript,"OFF")) {
  722.                       strcpy(buffer,Prescript);
  723.                       strcat(buffer," %ld");
  724.                       sprintf(buffer1,buffer,&Arexx);
  725.                       OkFlag = !SendRxMsg(buffer1,FALSE);
  726.                       if (!OkFlag) {
  727.                        e = (char *)-1;
  728.                       }
  729.                      }
  730.                    if (OkFlag && Do && ((!Pic1_Open) || (Single == 2) || (Single == 3))) {
  731.                  if (Pic2_Open) {
  732.                     Close24bit(&Pic2);
  733.                     Pic2_Open = FALSE;
  734.                    }
  735.                   if (Pic1_Open) {
  736.                    Close24bit(&Pic1);
  737.                    Pic1_Open = FALSE;
  738.                   }
  739.                       OkFlag = LoadFrames(TRUE,TRUE,TRUE);
  740.                       if (!OkFlag) {
  741.                        e = (char *)-1;
  742.                       }
  743.                      }
  744.                      if ((PointCount < 3) && OkFlag) {
  745.                       Error("Must have at least 3 points","Quit",NULL,H_3Points);
  746.                       OkFlag = FALSE;
  747.                      }
  748.                      if (Do && OkFlag) {
  749.                       // If we have calculated time per image the display it, update other gadgets
  750.                       if (t2) {
  751.                        sprintf(tbuffer,"%ld Seconds for last image",time2.tv_secs);
  752.                      AddMessage(tbuffer);
  753.                       }
  754.                       else {
  755.                      AddMessage("Rendering image");
  756.                     }
  757.                     if (TimerBase) {
  758.                      GetSysTime(&time1);
  759.                     }
  760.                       // We want to do this image so calculate coordinates in this image
  761.                       if ((Single == 1) || (Single == 3)) {
  762.                        for (MyPointp = (struct MyPoint *)PointList.lh_Head;
  763.                             MyPointp->MyNode.mln_Succ;
  764.                            MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
  765.                            MyPointp->Cx = (MyPointp->x1*(1024-move)+MyPointp->x*move)>>10;
  766.                            MyPointp->Cy = (MyPointp->y1*(1024-move)+MyPointp->y*move)>>10;
  767.                      }
  768.                     }
  769.                     else {
  770.                        for (MyPointp = (struct MyPoint *)PointList.lh_Head;
  771.                              MyPointp->MyNode.mln_Succ;
  772.                             MyPointp = (struct MyPoint *)MyPointp->MyNode.mln_Succ) {
  773.                             MyPointp->Cx = (MyPointp->x1*(1024-move)+MyPointp->x*move)>>10;
  774.                             MyPointp->Cy = (MyPointp->y1*(1024-move)+MyPointp->y*move)>>10;
  775.                      }
  776.                     }
  777.                     // Initialise chunky pointers
  778.                      arrayr=RED;
  779.                      arrayg=GREEN;
  780.                      arrayb=BLUE;
  781.                      // loop thru lines
  782.                         for (y=0;
  783.                         (y<height) && OkFlag;
  784.                         y++) {
  785.                         // Update progress
  786.                       GT_SetGadgetAttrs(ProgressGadgets[GDX_Line],ProgressWnd,NULL,
  787.                                                  GTSL_Level,(ULONG)y,TAG_END);
  788.                          // Loop thru columns
  789.                       for (x=0;
  790.                       x < width;
  791.                        x++) {
  792.                       // Determine coordinates on end image(s)
  793.                       FindPoint(&MyPoint);
  794.                       if (AntiAlias) {
  795.                        // Horrible AntiAlias stuff
  796.                        xbig = floor(MyPoint.xd + 0.5);
  797.                        xsmall = MyPoint.xd - (double)xbig;
  798.                        if (xsmall > 0) {
  799.                         right = 1;
  800.                        }
  801.                        else {
  802.                         xsmall = -xsmall;
  803.                         right = -1;
  804.                        }
  805.                        ybig = floor(MyPoint.yd + 0.5);
  806.                        ysmall = MyPoint.yd - (double)ybig;
  807.                        if (ysmall > 0) {
  808.                         down = swidth;
  809.                        }
  810.                        else {
  811.                         ysmall = -ysmall;
  812.                         down = -swidth;
  813.                        }
  814.                        offset = ybig*swidth+xbig;
  815.                        a = 1.0 + (xsmall * ysmall) - xsmall - ysmall;
  816.                        bb = xsmall * (1.0 - ysmall);
  817.                        c = ysmall * (1.0 - xsmall);
  818.                        d = xsmall * ysmall;
  819.                        if ((Single != 1) && (Single != 3)) {
  820.                       xbig1 = floor(MyPoint.x1d + 0.5);
  821.                         xsmall1 = MyPoint.x1d - (double)xbig1;
  822.                         if (xsmall1 > 0) {
  823.                          right1 = 1;
  824.                         }
  825.                         else {
  826.                          xsmall1 = -xsmall1;
  827.                          right1 = -1;
  828.                         }
  829.                         ybig1 = floor(MyPoint.y1d + 0.5);
  830.                         ysmall1 = MyPoint.y1d - (double)ybig1;
  831.                         if (ysmall1 > 0) {
  832.                          down1 = swidth;
  833.                         }
  834.                         else {
  835.                          ysmall1 = -ysmall1;
  836.                          down1 = -swidth;
  837.                         }
  838.                         offset1 = ybig1*swidth+xbig1;
  839.                         a1 = 1.0 + (xsmall1 * ysmall1) - xsmall1 - ysmall1;
  840.                         b1 = xsmall1 * (1.0 - ysmall1);
  841.                         c1 = ysmall1 * (1.0 - xsmall1);
  842.                         d1 = xsmall1 * ysmall1;
  843.                         (*arrayr) = min(max((((ULONG)
  844.                                                         ((((double)  Pic1.red[offset])*a + ((double)  Pic1.red[offset+right])*bb+
  845.                                                      ((double)  Pic1.red[offset+down])*c+((double)  Pic1.red[offset+down+right])*d)*((double)r) +
  846.                                                         (((double)  Pic2.red[offset1])*a1 + ((double)  Pic2.red[offset1+right1])*b1+
  847.                                                      ((double)  Pic2.red[offset1+down1])*c1+((double)  Pic2.red[offset1+down1+right1])*d1)*((double)r2))
  848.                                                     )>>10) + rplus - rminus,0),255);
  849.                         (*arrayg) = min(max((((ULONG)
  850.                                                         ((((double)Pic1.green[offset])*a + ((double)Pic1.green[offset+right])*bb+
  851.                                                      ((double)Pic1.green[offset+down])*c+((double)Pic1.green[offset+down+right])*d)*((double)g) +
  852.                                                         (((double)Pic2.green[offset1])*a1 + ((double)Pic2.green[offset1+right1])*b1+
  853.                                                      ((double)Pic2.green[offset1+down1])*c1+((double)Pic2.green[offset1+down1+right1])*d1)*((double)g2))
  854.                                                     )>>10) + gplus - gminus,0),255);
  855.                         (*arrayb) = min(max((((ULONG)
  856.                                                         ((((double) Pic1.blue[offset])*a + ((double) Pic1.blue[offset+right])*bb+
  857.                                                      ((double) Pic1.blue[offset+down])*c+((double) Pic1.blue[offset+down+right])*d)*((double)b) +
  858.                                                         (((double) Pic2.blue[offset1])*a1 + ((double) Pic2.blue[offset1+right1])*b1+
  859.                                                      ((double) Pic2.blue[offset1+down1])*c1+((double) Pic2.blue[offset1+down1+right1])*d1)*((double)b2))
  860.                                                     )>>10) + bplus - bminus,0),255);
  861.                        }
  862.                        else {
  863.                         (*arrayr) = min(max(((ULONG)
  864.                                                         (((((double)Pic1.red[offset])*a + ((double)Pic1.red[offset+right])*bb+
  865.                                                      ((double)Pic1.red[offset+down])*c+((double)Pic1.red[offset+down+right])*d)
  866.                                                     )*((double)r))>>10) + rplus - rminus,0),255);
  867.                           (*arrayg) = min(max(((ULONG)
  868.                                                     (((((double)Pic1.green[offset])*a + ((double)Pic1.green[offset+1])*bb+
  869.                                                      ((double)Pic1.green[offset+down])*c+((double)Pic1.green[offset+down+right])*d)
  870.                                                       )*((double)g))>>10) + gplus - gminus,0),255);
  871.                            (*arrayb) = min(max(((ULONG)
  872.                                                         (((((double)Pic1.blue[offset])*a + ((double)Pic1.blue[offset+1])*bb+
  873.                                                      ((double)Pic1.blue[offset+down])*c+((double)Pic1.blue[offset+down+right])*d)
  874.                                                        )*((double)b))>>10) + bplus - bminus,0),255);
  875.                        }
  876.                       }
  877.                       else {
  878.                        // Calculate new colours (without AntiAlias)
  879.                        offset = MyPoint.y*swidth+MyPoint.x;
  880.                        if ((Single == 1) || (Single == 3)) {
  881.                         (*arrayr) = min(max(((Pic1.red[offset]*r)>>10) + rplus - rminus,0),255);
  882.                           (*arrayg) = min(max(((Pic1.green[offset]*g)>>10) + gplus - gminus,0),255);
  883.                            (*arrayb) = min(max(((Pic1.blue[offset]*b)>>10) + bplus - bminus,0),255);
  884.                          }
  885.                          else {
  886.                       offset1 = MyPoint.y1*swidth+MyPoint.x1;
  887.                         (*arrayr) = min(max((((Pic2.red[offset1]*r2) +
  888.                                              (Pic1.red[offset]*r))>>10) + rplus - rminus,0),255);
  889.                           (*arrayg) = min(max((((Pic2.green[offset1]*g2) +
  890.                                          (Pic1.green[offset]*g))>>10) + gplus - gminus,0),255);
  891.                            (*arrayb) = min(max((((Pic2.blue[offset1]*b2) +
  892.                                              (Pic1.blue[offset]*b))>>10) + bplus - bminus,0),255);
  893.                          }
  894.                         }
  895.                         // If we are skipping columns then copy colour forward
  896.                         if (DX) {
  897.                            xr = *arrayr;
  898.                          xg = *arrayg;
  899.                          xb = *arrayb;
  900.                          x++;
  901.                          for (myx = 0;
  902.                                   (myx < DX) && (x < width);
  903.                                   x++,myx++) {
  904.                            arrayr++;
  905.                           *arrayr = xr;
  906.                        arrayg++;
  907.                           *arrayg = xg;
  908.                           arrayb++;
  909.                           *arrayb = xb;
  910.                          }
  911.                          x--;
  912.                         }
  913.                         // next column (if not already there)
  914.                         if (x < width) {
  915.                          arrayr++;
  916.                       arrayg++;
  917.                          arrayb++;
  918.                         }
  919.                         }
  920.                         // end of line, check 'Stop' and 'Help'
  921.                         OkFlag = HandleProgressIDCMP();
  922.                    if (handle) {
  923.                      while (agm = GetAmigaGuideMsg(handle)) {
  924.                        ReplyAmigaGuideMsg(agm);
  925.                      }
  926.                     }
  927.                     // skip part word at end of line
  928.                         arrayr += (swidth - width);
  929.                         arrayg += (swidth - width);
  930.                         arrayb += (swidth - width);
  931.                         // if skipping lines then copy previous line
  932.                         if (DY) {
  933.                          y++;
  934.                           for (myy = 0;
  935.                               (myy < DY) && (y<height);
  936.                               y++, myy++) {
  937.                           memcpy(arrayr, arrayr - swidth, swidth);
  938.                           arrayr += swidth;
  939.                           memcpy(arrayg, arrayg - swidth, swidth);
  940.                           arrayg += swidth;
  941.                           memcpy(arrayb, arrayb - swidth, swidth);
  942.                           arrayb += swidth;
  943.                          }
  944.                          y--;
  945.                         }
  946.                       }
  947.                       // not ok - already displayed an error
  948.                       if (!OkFlag) {
  949.                        e = (char *)-1;
  950.                   }
  951.                       else {
  952.                        // Save image
  953.                        OkFlag = SaveFile();
  954.                        // Caclulate time (if we have not already)
  955.                       if (TimerBase) {
  956.                         GetSysTime(&time2);
  957.                         t2 = TRUE;
  958.                         SubTime(&time2,&time1);
  959.                         }
  960.                         // Not ok - already displayed error message
  961.                         if (!OkFlag) {
  962.                         e = (char *)-1;
  963.                        }
  964.                          }
  965.                   }
  966.                  }
  967.                  if (OkFlag && ((Single == 0) || (Single == 2))) {
  968.                      // Pass to ARexx for processing
  969.                       if (strcmp(Prescript,"OFF")) {
  970.                      AddMessage("Prescript for last frame");
  971.                     f = Frames+1;
  972.                     Do = 0;
  973.                       strcpy(buffer,Prescript);
  974.                       strcat(buffer," %ld");
  975.                       sprintf(buffer1,buffer,&Arexx);
  976.                       OkFlag = !SendRxMsg(buffer1,FALSE);
  977.                       if (!OkFlag) {
  978.                        e = (char *)-1;
  979.                       }
  980.                     if (OkFlag && Do && ((!Pic1_Open) || (Single == 2))) {
  981.                   if (Pic2_Open) {
  982.                      Close24bit(&Pic2);
  983.                      Pic2_Open = FALSE;
  984.                     }
  985.                    if (Pic1_Open) {
  986.                     Close24bit(&Pic1);
  987.                     Pic1_Open = FALSE;
  988.                    }
  989.                        OkFlag = LoadFrames(FALSE,FALSE,TRUE);
  990.                        if (!OkFlag) {
  991.                         e = (char *)-1;
  992.                        }
  993.                       }
  994.                       if (OkFlag && Do) {
  995.                       AddMessage("Saving last frame");
  996.                        memcpy(RED,Pic2.red,swidth*height);
  997.                        memcpy(GREEN,Pic2.green,swidth*height);
  998.                        memcpy(BLUE,Pic2.blue,swidth*height);
  999.                        OkFlag = SaveFile();
  1000.                      if (!OkFlag) {
  1001.                       e = (char *)-1;
  1002.                      }
  1003.                       }
  1004.                      }
  1005.                     }
  1006.                 }
  1007.                    AddMessage("Cleaning up");
  1008.                    DeleteAllPoints();
  1009.                    if (RED) FreeVec(RED);
  1010.                    if (GREEN) FreeVec(GREEN);
  1011.                if (BLUE) FreeVec(BLUE);
  1012.                if (OScrn) {
  1013.                 FreeScreen24(OScrn);
  1014.                }
  1015.                else {    // Should not need this if else
  1016.                    if (!PPM) {
  1017.                   if (Planes[0]) FreeRaster(Planes[0],width,height);
  1018.                  if (Planes[1]) FreeRaster(Planes[1],width,height);
  1019.                  if (Planes[2]) FreeRaster(Planes[2],width,height);
  1020.                  if (!DCTV3) {
  1021.                   if (Planes[3]) FreeRaster(Planes[3],width,height);
  1022.                   if (!BW16 && !DCTV4) {
  1023.                    if (Planes[4]) FreeRaster(Planes[4],width,height);
  1024.                    if (Planes[5]) FreeRaster(Planes[5],width,height);
  1025.                    if (!HAM6) {
  1026.                     if (Planes[6]) FreeRaster(Planes[6],width,height);
  1027.                     if (Planes[7]) FreeRaster(Planes[7],width,height);
  1028.                     if (!HAM8 && !BW256) {
  1029.                      if (Planes[8]) FreeRaster(Planes[8],width,height);
  1030.                      if (Planes[9]) FreeRaster(Planes[9],width,height);
  1031.                      if (Planes[10]) FreeRaster(Planes[10],width,height);
  1032.                      if (Planes[11]) FreeRaster(Planes[11],width,height);
  1033.                      if (Planes[12]) FreeRaster(Planes[12],width,height);
  1034.                      if (Planes[13]) FreeRaster(Planes[13],width,height);
  1035.                      if (Planes[14]) FreeRaster(Planes[14],width,height);
  1036.                      if (Planes[15]) FreeRaster(Planes[15],width,height);
  1037.                      if (Planes[16]) FreeRaster(Planes[16],width,height);
  1038.                      if (Planes[17]) FreeRaster(Planes[17],width,height);
  1039.                      if (Planes[18]) FreeRaster(Planes[18],width,height);
  1040.                      if (Planes[19]) FreeRaster(Planes[19],width,height);
  1041.                      if (Planes[20]) FreeRaster(Planes[20],width,height);
  1042.                      if (Planes[21]) FreeRaster(Planes[21],width,height);
  1043.                      if (Planes[22]) FreeRaster(Planes[22],width,height);
  1044.                      if (Planes[23]) FreeRaster(Planes[23],width,height);
  1045.                     }
  1046.                    }
  1047.                   }
  1048.                  }
  1049.                 }
  1050.                }
  1051.                 if (!Alloced && !e) {
  1052.                  e = "Error AllocVec for output";
  1053.                  e1 = NULL;
  1054.                  hnum = H_AllocVec;
  1055.                 }
  1056.                }
  1057.                else {
  1058.                 e = (char *)-1;
  1059.                }
  1060.                if (OkFlag) {
  1061.                 e = (char *)-1;
  1062.                }
  1063.                if (!e) {
  1064.                  e = "Error Opening points file";
  1065.                 e1 = NULL;
  1066.                 hnum = H_OpenPoints;
  1067.                }
  1068.                if (Pic2_Open) {
  1069.                 Close24bit(&Pic2);
  1070.                 Pic2_Open = FALSE;
  1071.                }
  1072.               if (Pic1_Open) {
  1073.                Close24bit(&Pic1);
  1074.                Pic1_Open = FALSE;
  1075.               }
  1076.                 if (plane0) FreeVec(plane0);
  1077.                 if (plane1) FreeVec(plane1);
  1078.                 if (plane2) FreeVec(plane2);
  1079.                 if (plane3) FreeVec(plane3);
  1080.                 if (plane4) FreeVec(plane4);
  1081.                 if (plane5) FreeVec(plane5);
  1082.                 if (plane6) FreeVec(plane6);
  1083.                 if (plane7) FreeVec(plane7);
  1084.                 // reset requesters
  1085.               process->pr_WindowPtr = oldWindowPtr;
  1086.              }
  1087.              else {
  1088.               e = "Error opening progress window";
  1089.               e1 = NULL;
  1090.               hnum = H_Progress;
  1091.              }
  1092.              // close down everything
  1093.              CloseProgressWindow();
  1094.              CloseDownScreen();
  1095.                MyArgArrayDone();
  1096.             CloseLibrary(DiskfontBase);
  1097.           }
  1098.           if (!e) {
  1099.            e = "Unable to Open %s";
  1100.            e1 = "diskfont.library(36)";
  1101.            hnum = H_Library;
  1102.           }
  1103.           CloseLibrary(IconBase);
  1104.           }
  1105.           if (!e) {
  1106.            e = "Unable to Open %s";
  1107.            e1 = "icon.library(37)";
  1108.            hnum = H_Library;
  1109.           }
  1110.           CloseLibrary(UtilityBase);
  1111.          }
  1112.         if (!e) {
  1113.          e = "Unable to Open %s";
  1114.          e1= "utility.library(37)";
  1115.          hnum = H_Library;
  1116.         }
  1117.         CloseLibrary(AslBase);
  1118.        }
  1119.        if (!e) {
  1120.         e = "Unable to Open %s";
  1121.         e1 = "asl.library(37)";
  1122.         hnum = H_Library;
  1123.        }
  1124.        CloseLibrary(GadToolsBase);
  1125.       }
  1126.       if (!e) {
  1127.        e = "Unable to Open %s";
  1128.        e1 = "gadtools.library(37)";
  1129.        hnum = H_Library;
  1130.       }
  1131.       CloseLibrary(LayersBase);
  1132.      }
  1133.      if (!e) {
  1134.       e = "Unable to Open %s";
  1135.       e1 = "layers.library(37)";
  1136.       hnum = H_Library;
  1137.      }
  1138.      CloseLibrary(GfxBase);
  1139.     }
  1140.     if (!e) {
  1141.      e = "Unable to Open %s";
  1142.      e1 = "graphics.library(37)";
  1143.      hnum = H_Library;
  1144.     }
  1145.     CloseLibrary(IFFParseBase);
  1146.    }
  1147.    if (!e) {
  1148.     e = "Unable to Open %s";
  1149.     e1 = "iffparse.library(37)";
  1150.     hnum = H_Library;
  1151.    }
  1152.    CloseLibrary(RexxSysBase);
  1153.   }
  1154.   if (!e) {
  1155.    e = "Unable to Open %s";
  1156.    e1 = "rexxsyslib.library(0)";
  1157.    hnum = H_Library;
  1158.   }
  1159.   // Display an error message
  1160.   if (e != (char *)-1) {
  1161.    Error(e,"Quit",e1,hnum);
  1162.   }
  1163.  }
  1164.  if (OpalBase) {
  1165.   CloseLibrary((struct Library *)OpalBase);
  1166.  }
  1167.  if (TimerBase) {
  1168.   CloseDevice((struct IORequest *) &tr);
  1169.  }
  1170.  if (AmigaGuideBase) {
  1171.   if (handle) {
  1172.      CloseAmigaGuide(handle);
  1173.   }
  1174.   CloseLibrary(AmigaGuideBase);
  1175.  }
  1176.  if (DCTVBase) {
  1177.   CloseLibrary(DCTVBase);
  1178.  }
  1179.  if (ReqToolsBase) {
  1180.   CloseLibrary(ReqToolsBase);
  1181.  }
  1182. }
  1183.  
  1184. // save an image
  1185. BOOL
  1186. SaveFile(void) {
  1187.     struct ILBMInfo     *ilbm;        // IFF stuff to save
  1188.     BPTR                    fh;            // File handle for PPM
  1189.     BOOL OkFlag = TRUE;
  1190.     struct BitMap     TBM;                // Temp bit map
  1191.     struct DiskObject *MyDiskObject;    // The Icon
  1192.     char                    *iconname;    // iconname
  1193.     char                    *iconname1;    // alternate iconname
  1194.     if (!PPM) {
  1195.         // Not PPM
  1196.         if (OVFormat) {
  1197.             // OpalVision so convert RGB to OpalVision
  1198.             RGBtoOV(OScrn,p,0,0,swidth,height);
  1199.         }
  1200.         else {
  1201.             // Set up BitMap
  1202.             InitBitMap(&MyBitMap,(DCTV3?3:((DCTV4|BW16)?4:(HAM6?6:((HAM8|BW256)?8:24)))),width,height);
  1203.             InitRastPort(&RP);
  1204.             RP.BitMap = &MyBitMap;
  1205.             InitRastPort(&TRP);
  1206.             InitBitMap(&TBM,(DCTV3?3:((DCTV4|BW16)?4:(HAM6?6:((HAM8|BW256)?8:8)))),width,1);
  1207.             TBM.BytesPerRow = (((width+15)>>4)<<1);
  1208.             TBM.Rows = 1;
  1209.             TRP.BitMap = &TBM;
  1210.             TBM.Planes[0]=plane0;
  1211.             TBM.Planes[1]=plane1;
  1212.             TBM.Planes[2]=plane2;
  1213.             TBM.Planes[3]=plane3;
  1214.             TBM.Planes[4]=plane4;
  1215.             TBM.Planes[5]=plane5;
  1216.             TBM.Planes[6]=plane6;
  1217.             TBM.Planes[7]=plane7;
  1218.             if (!HAM6 && !HAM8 && !BW16 && !BW256 && !DCTV3 && !DCTV4) {
  1219.                 // i.e. 24 bit ILBM?
  1220.                 // so convert chunky to planar
  1221.                 MyBitMap.BitMap.Depth = 8;
  1222.                 MyBitMap.BitMap.Planes[0] = Planes[0];
  1223.                 MyBitMap.BitMap.Planes[1] = Planes[1];
  1224.                 MyBitMap.BitMap.Planes[2] = Planes[2];
  1225.                 MyBitMap.BitMap.Planes[3] = Planes[3];
  1226.                 MyBitMap.BitMap.Planes[4] = Planes[4];
  1227.                 MyBitMap.BitMap.Planes[5] = Planes[5];
  1228.                 MyBitMap.BitMap.Planes[6] = Planes[6];
  1229.                 MyBitMap.BitMap.Planes[7] = Planes[7];
  1230.                 WritePixelArray8(&RP,0,0,width-1,height-1,RED,&TRP);
  1231.                 WaitBlit();
  1232.                 MyBitMap.BitMap.Planes[0] = Planes[8];
  1233.                 MyBitMap.BitMap.Planes[1] = Planes[9];
  1234.                 MyBitMap.BitMap.Planes[2] = Planes[10];
  1235.                 MyBitMap.BitMap.Planes[3] = Planes[11];
  1236.                 MyBitMap.BitMap.Planes[4] = Planes[12];
  1237.                 MyBitMap.BitMap.Planes[5] = Planes[13];
  1238.                 MyBitMap.BitMap.Planes[6] = Planes[14];
  1239.                 MyBitMap.BitMap.Planes[7] = Planes[15];
  1240.                 WritePixelArray8(&RP,0,0,width-1,height-1,GREEN,&TRP);
  1241.                 WaitBlit();
  1242.                 MyBitMap.BitMap.Planes[0] = Planes[16];
  1243.                 MyBitMap.BitMap.Planes[1] = Planes[17];
  1244.                 MyBitMap.BitMap.Planes[2] = Planes[18];
  1245.                 MyBitMap.BitMap.Planes[3] = Planes[19];
  1246.                 MyBitMap.BitMap.Planes[4] = Planes[20];
  1247.                 MyBitMap.BitMap.Planes[5] = Planes[21];
  1248.                 MyBitMap.BitMap.Planes[6] = Planes[22];
  1249.                 MyBitMap.BitMap.Planes[7] = Planes[23];
  1250.                 WritePixelArray8(&RP,0,0,width-1,height-1,BLUE,&TRP);
  1251.                 WaitBlit();
  1252.             }
  1253.             // Reset up BitMap
  1254.             MyBitMap.BitMap.Depth = (DCTV3?3:((DCTV4|BW16)?4:(HAM6?6:((HAM8|BW256)?8:24))));
  1255.             MyBitMap.BitMap.Planes[0] = Planes[0];
  1256.             MyBitMap.BitMap.Planes[1] = Planes[1];
  1257.             MyBitMap.BitMap.Planes[2] = Planes[2];
  1258.             MyBitMap.BitMap.Planes[3] = Planes[3];
  1259.             MyBitMap.BitMap.Planes[4] = Planes[4];
  1260.             MyBitMap.BitMap.Planes[5] = Planes[5];
  1261.             MyBitMap.BitMap.Planes[6] = Planes[6];
  1262.             MyBitMap.BitMap.Planes[7] = Planes[7];
  1263.             MyBitMap.BitMap.Planes[8] = Planes[8];
  1264.             MyBitMap.BitMap.Planes[9] = Planes[9];
  1265.             MyBitMap.BitMap.Planes[10] = Planes[10];
  1266.             MyBitMap.BitMap.Planes[11] = Planes[11];
  1267.             MyBitMap.BitMap.Planes[12] = Planes[12];
  1268.             MyBitMap.BitMap.Planes[13] = Planes[13];
  1269.             MyBitMap.BitMap.Planes[14] = Planes[14];
  1270.             MyBitMap.BitMap.Planes[15] = Planes[15];
  1271.             MyBitMap.BitMap.Planes[16] = Planes[16];
  1272.             MyBitMap.BitMap.Planes[17] = Planes[17];
  1273.             MyBitMap.BitMap.Planes[18] = Planes[18];
  1274.             MyBitMap.BitMap.Planes[19] = Planes[19];
  1275.             MyBitMap.BitMap.Planes[20] = Planes[20];
  1276.             MyBitMap.BitMap.Planes[21] = Planes[21];
  1277.             MyBitMap.BitMap.Planes[22] = Planes[22];
  1278.             MyBitMap.BitMap.Planes[23] = Planes[23];
  1279.         }
  1280.     }
  1281.     // Set up output file name
  1282.    sprintf(FileName,AnimName,f+Start-1);
  1283.     if (PPM) {
  1284.         // PPM Save is very simple P6 mode
  1285.         AddMessage("Saving PPM image");
  1286.         if (fh = Open(FileName,MODE_NEWFILE)) {
  1287.             sprintf(buffer,"P6\n%ld %ld\n255\n",width,height);
  1288.             FPuts(fh,buffer);
  1289.             arrayr=RED;
  1290.             arrayg=GREEN;
  1291.             arrayb=BLUE;
  1292.             // loop thru lines
  1293.             for (y=0;
  1294.                   (y<height) && OkFlag;
  1295.                   y++) {
  1296.                 // Loop thru columns
  1297.                 for (x=0;
  1298.                       x < width;
  1299.                       x++) {
  1300.                     FPutC(fh,*arrayr);
  1301.                     FPutC(fh,*arrayg);
  1302.                     FPutC(fh,*arrayb);
  1303.                     arrayr++;
  1304.                     arrayg++;
  1305.                     arrayb++;
  1306.                 }
  1307.                 // skip part word at end of line
  1308.                 arrayr += (swidth - width);
  1309.                 arrayg += (swidth - width);
  1310.                 arrayb += (swidth - width);
  1311.             }
  1312.             if (!Close(fh)) {
  1313.                 OkFlag = FALSE;
  1314.             }
  1315.         }
  1316.         else {
  1317.             OkFlag = FALSE;
  1318.         }
  1319.     }
  1320.     else {
  1321.         // Save non PPM
  1322.         if (OVFormat) {
  1323.             // Save OpalVision
  1324.             if (!strcmp(OVFormat,"JPG")) {
  1325.                 AddMessage("Saving Opal JPEG image");
  1326.                 // Save JPEG
  1327.                 OkFlag = !SaveJPEG24(OScrn,FileName,(OVThumb?0:NOTHUMBNAIL),OVQuality);
  1328.             }
  1329.             else {
  1330.                 AddMessage("Saving Opal IFF24 image");
  1331.                 // Save IFF
  1332.                 OkFlag = !SaveIFF24(OScrn,FileName,NULL,(OVThumb?0:NOTHUMBNAIL)|(OVFast?OVFASTFORMAT:0));
  1333.             }
  1334.         }
  1335.         else {
  1336.             if (HAM6) {
  1337.                 AddMessage("Saving HAM6 image");
  1338.                 OkFlag = SaveHAM6(FileName,width,height,swidth,
  1339.                                         pwidth,pheight,pmode,
  1340.                                         RED,GREEN,BLUE,&RP,&TRP);
  1341.             }
  1342.             else {
  1343.                 if (HAM8) {
  1344.                     AddMessage("Saving HAM8 image");
  1345.                     OkFlag = SaveHAM8(FileName,width,height,swidth,
  1346.                                             pwidth,pheight,pmode,
  1347.                                             RED,GREEN,BLUE,&RP,&TRP);
  1348.                 }
  1349.                 else {
  1350.                     if (BW16) {
  1351.                         AddMessage("Saving BW16 image");
  1352.                         OkFlag = SaveBW16(FileName,width,height,swidth,
  1353.                                                 pwidth,pheight,pmode,
  1354.                                                 RED,GREEN,BLUE,&RP,&TRP);
  1355.                     }
  1356.                     else {
  1357.                         if (BW256) {
  1358.                             AddMessage("Saving BW256 image");
  1359.                             OkFlag = SaveBW256(FileName,width,height,swidth,
  1360.                                                      pwidth,pheight,pmode,
  1361.                                                      RED,GREEN,BLUE,&RP,&TRP);
  1362.                         }
  1363.                         else {
  1364.                             if (DCTV3 || DCTV4) {
  1365.                                 AddMessage(DCTV3?"Saving DCTV3 image":"Saving DCTV4 image");
  1366.                                 OkFlag = SaveDCTV(FileName,width,height,swidth,
  1367.                                                         pwidth,pheight,pmode,
  1368.                                                         RED,GREEN,BLUE,&RP,&TRP);
  1369.                             }
  1370.                             else {
  1371.                                 AddMessage("Saving ILBM24 image");
  1372.                                 // allocate some IFF stuff
  1373.                                 if (ilbm = (struct ILBMInfo *)AllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)) {
  1374.                                     if (ilbm->ParseInfo.iff = AllocIFF()) {
  1375.                                         OkFlag = !saveilbm(ilbm, &MyBitMap, pmode,
  1376.                                                                  width,  height, pwidth, pheight,
  1377.                                                                  NULL, 0, 0,    /* colortable */
  1378.                                                                  mskNone, 0,    /* masking, transparent */
  1379.                                                                  NULL, NULL,     /* chunklists */
  1380.                                                                  FileName);
  1381.                                         // Close everything down cleanly
  1382.                                         FreeIFF(ilbm->ParseInfo.iff);
  1383.                                     }
  1384.                                     else {
  1385.                                         OkFlag = FALSE;
  1386.                                     }
  1387.                                     FreeMem(ilbm,sizeof(struct ILBMInfo));
  1388.                                 }
  1389.                                 else {
  1390.                                     OkFlag = FALSE;
  1391.                                 }
  1392.                             }
  1393.                         }
  1394.                     }
  1395.                 }
  1396.             }
  1397.         }
  1398.     }
  1399.     if (OkFlag) {
  1400.         if (CreateIcons) {
  1401.             // try to save an Icon
  1402.             if (MyDiskObject = GetDiskObject(FileName)) {
  1403.                 // Do not overwrite if already present
  1404.                 FreeDiskObject(MyDiskObject);
  1405.             }
  1406.             else {
  1407.                 // Set up two possible names
  1408.                 if (OVFormat) {
  1409.                     if (!strcmp(OVFormat,"JPG")) {
  1410.                         iconname = "ENV:TSMorph/def_jpg";
  1411.                         iconname1 = "ENV:SYS/def_jpg";
  1412.                     }
  1413.                     else {
  1414.                         iconname = "ENV:TSMorph/def_iff";
  1415.                         iconname1 = "ENV:SYS/def_iff";
  1416.                     }
  1417.                 }
  1418.                 else {
  1419.                     if (PPM) {
  1420.                         iconname = "ENV:TSMorph/def_ppm";
  1421.                         iconname1 = "ENV:SYS/def_ppm";
  1422.                     }
  1423.                     else {
  1424.                         if (BW16) {
  1425.                             iconname = "ENV:TSMorph/def_bw16";
  1426.                             iconname1 = "ENV:SYS/def_bw16";
  1427.                         }
  1428.                         else {
  1429.                             if (BW256) {
  1430.                                 iconname = "ENV:TSMorph/def_bw256";
  1431.                                 iconname1 = "ENV:SYS/def_bw256";
  1432.                             }
  1433.                             else {
  1434.                                 if (HAM6) {
  1435.                                     iconname = "ENV:TSMorph/def_ham6";
  1436.                                     iconname1 = "ENV:SYS/def_ham6";
  1437.                                 }
  1438.                                 else {
  1439.                                     if (HAM8) {
  1440.                                         iconname = "ENV:TSMorph/def_ham8";
  1441.                                         iconname1 = "ENV:SYS/def_ham8";
  1442.                                     }
  1443.                                     else {
  1444.                                         if (DCTV3) {
  1445.                                             iconname = "ENV:TSMorph/def_dctv3";
  1446.                                             iconname1 = "ENV:SYS/def_dctv3";
  1447.                                         }
  1448.                                         else {
  1449.                                             if (DCTV4) {
  1450.                                                 iconname = "ENV:TSMorph/def_dctv4";
  1451.                                                 iconname1 = "ENV:SYS/def_dctv4";
  1452.                                             }
  1453.                                             else {
  1454.                                                 iconname = "ENV:TSMorph/def_ilbm";
  1455.                                                 iconname1 = "ENV:SYS/def_ilbm";
  1456.                                             }
  1457.                                         }
  1458.                                     }
  1459.                                 }
  1460.                             }
  1461.                         }
  1462.                     }
  1463.                 }
  1464.                 // Try two names, as last resort use default project
  1465.                 if ((MyDiskObject = GetDiskObject(iconname)) ||
  1466.                      (MyDiskObject = GetDiskObject(iconname1)) ||
  1467.                      (MyDiskObject = GetDefDiskObject(WBPROJECT))) {
  1468.                     PutDiskObject(FileName,MyDiskObject);
  1469.                     FreeDiskObject(MyDiskObject);
  1470.                 }
  1471.             }
  1472.         }
  1473.     }
  1474.     if (!OkFlag) {
  1475.         Error("Error saving file '%s'","Quit",FileName,H_ESave);
  1476.     }
  1477.     else {
  1478.         // Post image processing
  1479.         if (strcmp(Postscript,"OFF")) {
  1480.             strcpy(buffer,Postscript);
  1481.             strcat(buffer," %ld %ld %ld %s");
  1482.             sprintf(buffer1,buffer,f+Start-1,Frames,Single,FileName);
  1483.             AddMessage("Postscript processing");
  1484.             OkFlag = !SendRxMsg(buffer1,FALSE);
  1485.         }
  1486.     }
  1487.     return OkFlag;
  1488. }
  1489.  
  1490. extern UWORD FileFormat = 0;
  1491.  
  1492. /* recognized file formats */
  1493. #define FORMAT_IFF    1
  1494. #define FORMAT_JPEG    2
  1495. #define FORMAT_GIF    3
  1496. #define FORMAT_PPM    4
  1497. #define FORMAT_TARGA    5
  1498.  
  1499. /* Opens a 24 bit image
  1500.  * filename = name of file
  1501.  * pic        = structure to update
  1502.  * GUI        = TRUE to display error message
  1503.  * Returns      TRUE if ok
  1504.  */
  1505. BOOL
  1506. Load24bit(char *filename,struct Picture *pic,BOOL GUI) {
  1507.     char                     *e     = NULL;    // Error message main text
  1508.     char                    *e1     = NULL;    // sub text,
  1509.     struct RastPort     RP,                // Rastport
  1510.                             TRP;                // Temp rastport
  1511.     struct BitMap         BM,                // Bitmap
  1512.                             TBM;                // Temp bitmap
  1513.     ULONG                    hnum    = 0;        // Help on error
  1514.     BOOL                    OkFlag=TRUE;    // Still OK?
  1515.     char                    buffer[256],    // For Rexx Scripts
  1516.                             buffer1[256];
  1517.     long                    Err;                // Opal error
  1518.     BPTR                    fh;
  1519.     UBYTE zbuffer[5]="\0\0\0\0";
  1520.     decompress_info_ptr info;            // Load JPEG stuff
  1521.     UWORD i,j;
  1522.     LONG penno;
  1523.     struct RastPort    Rp;                // Rast port for conversion
  1524.     UBYTE *rx,*gx,*bx;
  1525.     UBYTE rr,gg,bb;
  1526.     UWORD EHB;
  1527.     BOOL isHAM6 = FALSE;
  1528.     BOOL isHAM8 = FALSE;
  1529.     BOOL isEHB = FALSE;
  1530.     struct DisplayInfo queryinfo;
  1531.     DisplayInfoHandle dhandle = NULL;
  1532.     struct DCTVCvtHandle    *chandle=NULL;    // DCTV conversion stuff
  1533.     UWORD                    *DCTVcolors=NULL;    // DCTV palette
  1534.  
  1535.     if (filename) {
  1536.        // Load image processing
  1537.         if (strcmp(Loadscript,"OFF")) {
  1538.             strcpy(buffer,Loadscript);
  1539.             strcat(buffer," %ld %ld %ld %ld %s");
  1540.             sprintf(buffer1,buffer,f+Start-1,Frames,Single,(pic==&Pic1)?0:1,filename);
  1541.              AddMessage("Loadscript processing");
  1542.           OkFlag = !SendRxMsg(buffer1,FALSE);
  1543.           if (!OkFlag) {
  1544.               e = (char *)-1;
  1545.               GUI = FALSE;    // Do not display error
  1546.           }
  1547.        }
  1548.         pic->rgbonelot = FALSE;
  1549.        if (!e) {
  1550.            // determine file format
  1551.             if (fh = Open(filename,MODE_OLDFILE)) {
  1552.                 FRead(fh,zbuffer,4,1);
  1553.                 if ((!strcmp(zbuffer,"FORM")) ||
  1554.                      (!strcmp(zbuffer,"CAT ")) ||
  1555.                      (!strcmp(zbuffer,"LIST"))) {
  1556.                     FileFormat = FORMAT_IFF;
  1557.                 }
  1558.                 else {
  1559.                     if ((zbuffer[0] == 0xFF) &&
  1560.                          (zbuffer[1] == 0xD8)) {
  1561.                         FileFormat = FORMAT_JPEG;
  1562.                     }
  1563.                     else {
  1564.                         if ((zbuffer[0] == 'G') &&
  1565.                              (zbuffer[1] == 'I') &&
  1566.                              (zbuffer[2] == 'F')) {
  1567.                             FileFormat = FORMAT_GIF;
  1568.                         }
  1569.                         else {
  1570.                             if ((zbuffer[0] == 'P') &&
  1571.                                  ((zbuffer[1] == '2') ||
  1572.                                   (zbuffer[1] == '3') ||
  1573.                                   (zbuffer[1] == '5') ||
  1574.                                   (zbuffer[1] == '6'))) {
  1575.                                 FileFormat = FORMAT_PPM;
  1576.                             }
  1577.                             else {
  1578.                                 FileFormat = FORMAT_TARGA;
  1579.                             }
  1580.                         }
  1581.                     }
  1582.                 }
  1583.                 Close(fh);
  1584.             }
  1585.             else {
  1586.                 e = "Error opening file '%s'";
  1587.                 e1 = filename;
  1588.                 hnum = H_Open;
  1589.                 OkFlag = FALSE;
  1590.             }
  1591.         }
  1592.         if (OkFlag) {
  1593.             AddMessage((pic == &Pic2)?"Loading image 2":"Loading image 1");
  1594.         }
  1595.        // We have a file name
  1596.         if (OkFlag && (FileFormat != FORMAT_IFF)) {
  1597.             // Not an IFF file so use JPEG code
  1598.            AddMessage((FileFormat == FORMAT_JPEG)?"Loading JFIF":
  1599.                            (FileFormat == FORMAT_GIF)?"Loading GIF":
  1600.                            (FileFormat == FORMAT_PPM)?"Loading PPM":
  1601.                            (FileFormat == FORMAT_TARGA)?"Loading Targa?":
  1602.                            "Loading ?");
  1603.             if ((info = LoadJPEG(filename,0,NULL,NULL,NULL,NULL)) &&
  1604.                  (info->output_file)) {
  1605.                AddMessage("Allocating work memory");
  1606.                 pic->rgbonelot = TRUE;
  1607.                 pic->red = (UBYTE *)info->output_file;
  1608.                 pic->green = pic->red + (((info->image_width+15)>>4)<<4) * info->image_height;
  1609.                 pic->blue = pic->green + (((info->image_width+15)>>4)<<4) * info->image_height;
  1610.                 // Allocate temp bit maps if first image and no OpalVision save
  1611.                 if ((OVFormat) || (plane0) ||
  1612.                            ((plane0 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1613.                             (plane1 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1614.                             (plane2 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1615.                             (plane3 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1616.                             (plane4 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1617.                             (plane5 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1618.                             (plane6 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1619.                             (plane7 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)))) {
  1620.                        return TRUE;
  1621.                  }
  1622.                  else {
  1623.                  e = "Unable to %s";
  1624.                   e1 = "allocate memory for bitmap";
  1625.                   hnum = H_AllocPlanes;
  1626.                  }
  1627.             }
  1628.         }
  1629.         if (OkFlag && (FileFormat == FORMAT_IFF)) {
  1630.             // Load iff
  1631.            AddMessage("Loading IFF");
  1632.             if (pic->ilbm = (struct ILBMInfo *)AllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)) {
  1633.                 // IFF stuff
  1634.                if (pic->ilbm->ParseInfo.iff = AllocIFF()) {
  1635.                    // more iff stuff
  1636.                     pic->ilbm->ParseInfo.propchks = props;
  1637.                     pic->ilbm->ParseInfo.collectchks = nowt;
  1638.                     pic->ilbm->ParseInfo.stopchks = stops;
  1639.                     // Load the image using IFF routines
  1640.                     if (!(loadbrush(pic->ilbm,filename))) {
  1641.                         // Close the file and validate
  1642.                         closeifile(&(pic->ilbm->ParseInfo));
  1643.                         pwidth  = width  < 320 ? 320 : width;
  1644.                      pheight = height < 200 ? 200 : height;
  1645.                             pmode   = pwidth >= 640  ? HIRES : 0L;
  1646.                      pmode  |= pheight >= 400 ? LACE  : 0L;
  1647.     // ??????        width = pic->ilbm->Bmhd.w;
  1648.                         // Allocate chunky bit maps
  1649.                        AddMessage("Allocating Bitmaps");
  1650.                         if ((pic->red = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
  1651.                              (pic->green = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
  1652.                              (pic->blue = AllocVec(((((pic->ilbm->Bmhd.w+15)>>4)<<4)*pic->ilbm->Bmhd.h),0)) &&
  1653.                                // Allocate temp bit maps if first image and no OpalVision save
  1654.                                ((OVFormat && (pic->ilbm->Bmhd.nPlanes != 24)) || (plane0) ||
  1655.                                ((plane0 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1656.                                 (plane1 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1657.                                 (plane2 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1658.                                 (plane3 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1659.                                 (plane4 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1660.                                 (plane5 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1661.                                 (plane6 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1662.                                 (plane7 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP))))) {
  1663.                             if (pic->ilbm->Bmhd.nPlanes == 24) {
  1664.                                 // Convert 24 bit planar to chunky
  1665.                                AddMessage("Converting 24 bit to Chunky");
  1666.                                 // Initialise rast ports/bitmaps
  1667.                                 InitRastPort(&RP);
  1668.                                 InitRastPort(&TRP);
  1669.                               InitBitMap(&TBM,8,pic->ilbm->Bmhd.w,1);
  1670.                                TRP.BitMap = &TBM;
  1671.                               TBM.Planes[0]=plane0;
  1672.                               TBM.Planes[1]=plane1;
  1673.                               TBM.Planes[2]=plane2;
  1674.                               TBM.Planes[3]=plane3;
  1675.                               TBM.Planes[4]=plane4;
  1676.                               TBM.Planes[5]=plane5;
  1677.                               TBM.Planes[6]=plane6;
  1678.                               TBM.Planes[7]=plane7;
  1679.                               InitBitMap(&BM,8,pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h);
  1680.                               RP.BitMap = &BM;
  1681.                                  BM.Planes[0] = pic->ilbm->brbitmap->Planes[0];
  1682.                               BM.Planes[1] = pic->ilbm->brbitmap->Planes[1];
  1683.                               BM.Planes[2] = pic->ilbm->brbitmap->Planes[2];
  1684.                               BM.Planes[3] = pic->ilbm->brbitmap->Planes[3];
  1685.                               BM.Planes[4] = pic->ilbm->brbitmap->Planes[4];
  1686.                               BM.Planes[5] = pic->ilbm->brbitmap->Planes[5];
  1687.                               BM.Planes[6] = pic->ilbm->brbitmap->Planes[6];
  1688.                               BM.Planes[7] = pic->ilbm->brbitmap->Planes[7];
  1689.                               // Convert red to chunky
  1690.                               ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->red,&TRP);
  1691.                             WaitBlit();
  1692.                                 BM.Planes[0] = pic->ilbm->brbitmap->Planes[8];
  1693.                               BM.Planes[1] = pic->ilbm->brbitmap->Planes[9];
  1694.                               BM.Planes[2] = pic->ilbm->brbitmap->Planes[10];
  1695.                               BM.Planes[3] = pic->ilbm->brbitmap->Planes[11];
  1696.                               BM.Planes[4] = pic->ilbm->brbitmap->Planes[12];
  1697.                               BM.Planes[5] = pic->ilbm->brbitmap->Planes[13];
  1698.                               BM.Planes[6] = pic->ilbm->brbitmap->Planes[14];
  1699.                               BM.Planes[7] = pic->ilbm->brbitmap->Planes[15];
  1700.                               // and green
  1701.                               ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->green,&TRP);
  1702.                             WaitBlit();
  1703.                               BM.Planes[0] = pic->ilbm->brbitmap->Planes[16];
  1704.                               BM.Planes[1] = pic->ilbm->brbitmap->Planes[17];
  1705.                               BM.Planes[2] = pic->ilbm->brbitmap->Planes[18];
  1706.                               BM.Planes[3] = pic->ilbm->brbitmap->Planes[19];
  1707.                               BM.Planes[4] = pic->ilbm->brbitmap->Planes[20];
  1708.                               BM.Planes[5] = pic->ilbm->brbitmap->Planes[21];
  1709.                               BM.Planes[6] = pic->ilbm->brbitmap->Planes[22];
  1710.                               BM.Planes[7] = pic->ilbm->brbitmap->Planes[23];
  1711.                               // and blue
  1712.                               ReadPixelArray8(&RP,0,0,pic->ilbm->Bmhd.w-1,pic->ilbm->Bmhd.h-1,pic->blue,&TRP);
  1713.                             WaitBlit();
  1714.                                AddMessage("Cleaning up");
  1715.                             // Set up stuff to write image
  1716.     // ????                    width = pic->ilbm->Bmhd.w;
  1717.     //    ????                    height = pic->ilbm->Bmhd.h;
  1718.                              // Unload everything and exit cleanly
  1719.                                 unloadbrush(pic->ilbm);
  1720.                                 FreeIFF(pic->ilbm->ParseInfo.iff);
  1721.                                 FreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1722.                               return TRUE;
  1723.                            }
  1724.                            else {
  1725.                                 if (DCTVBase && TestDCTVSignature(pic->ilbm->brbitmap)) {
  1726.                                     // Convert DCTV to chunky
  1727.                                     if (DCTVcolors = AllocVec(2L<<pic->ilbm->Bmhd.nPlanes,NULL)) {
  1728.                                         for (i=0; i < (1L<<pic->ilbm->Bmhd.nPlanes); ++i) {
  1729.                                             DCTVcolors[i] = ((pic->ilbm->RGB[i*4+1] & 0xf0) << 4) |
  1730.                                                                  ((pic->ilbm->RGB[i*4+2] & 0xf0)) |
  1731.                                                                  ((pic->ilbm->RGB[i*4+3] & 0xf0) >> 4);
  1732.                                         }
  1733.                                        AddMessage("Converting DCTV to Chunky");
  1734.                                         if (chandle = AllocDCTVCvtTags(pic->ilbm->brbitmap,
  1735.                                                         DCTVCVTA_Type, DCTVCVTT_DCTVtoRGB,
  1736.                                                         DCTVCVTA_Width, (((pic->ilbm->Bmhd.w+15)>>4)<<4),
  1737.                                                         DCTVCVTA_Height, pic->ilbm->Bmhd.h,
  1738.                                                         DCTVCVTA_Flags, ((pic->ilbm->camg & LACE)?DCTVCVTF_Lace:0)|
  1739.                                                                             DCTVCVTF_CustomRGBBuf,
  1740.                                                         DCTVCVTA_ColorTable, DCTVcolors,
  1741.                                                         TAG_END)) {
  1742.                                             chandle->Red = pic->red;
  1743.                                             chandle->Green = pic->green;
  1744.                                             chandle->Blue = pic->blue;
  1745.                                             while (chandle->DstLineNum < chandle->Height) {
  1746.                                                 CvtDCTVLine(chandle);
  1747.                                                 if ((chandle->DstLineNum > 0) &&
  1748.                                                      (chandle->DstLineNum <= chandle->Height)) {
  1749.                                                     chandle->Red += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
  1750.                                                     chandle->Green += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
  1751.                                                     chandle->Blue += (((pic->ilbm->Bmhd.w+15)>>4)<<4);
  1752.                                                 }
  1753.                                             }
  1754.                                             FreeVec(DCTVcolors);
  1755.                                             FreeDCTVCvt(chandle);
  1756.                                          // Unload everything and exit cleanly
  1757.                                             unloadbrush(pic->ilbm);
  1758.                                             FreeIFF(pic->ilbm->ParseInfo.iff);
  1759.                                             FreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1760.                                             return TRUE;
  1761.                                         }
  1762.                                         FreeVec(DCTVcolors);
  1763.                                     }
  1764.                                 }
  1765.                                 else {
  1766.                                     // determine special IFF mode
  1767.                                     if ((dhandle = FindDisplayInfo(pic->ilbm->camg)) &&
  1768.                                          (GetDisplayInfoData(dhandle,(UBYTE *)&queryinfo,sizeof(queryinfo),DTAG_DISP,NULL))) {
  1769.                                         if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
  1770.                                            AddMessage("Converting HAM6 to Chunky");
  1771.                                             isHAM6 = TRUE;
  1772.                                         }
  1773.                                         else {
  1774.                                             if ((pic->ilbm->Bmhd.nPlanes == 8) && (queryinfo.PropertyFlags & DIPF_IS_HAM)) {
  1775.                                                 isHAM8 = TRUE;
  1776.                                                AddMessage("Converting HAM8 to Chunky");
  1777.                                             }
  1778.                                             else {
  1779.                                                   if ((pic->ilbm->Bmhd.nPlanes == 6) && (queryinfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE)) {
  1780.                                                       isEHB = TRUE;
  1781.                                                    AddMessage("Converting EHB to Chunky");
  1782.                                                   }
  1783.                                                   else {
  1784.                                                    AddMessage("Converting ILBM to Chunky");
  1785.                                                   }
  1786.                                             }
  1787.                                         }
  1788.                                     }
  1789.                                     // Convert to chunky
  1790.                                     InitRastPort(&Rp);
  1791.                                     Rp.BitMap = pic->ilbm->brbitmap;
  1792.                                     rx = pic->red;
  1793.                                     gx = pic->green;
  1794.                                     bx = pic->blue;
  1795.                                     // For each line
  1796.                                     for (j = 0;
  1797.                                          j < height;
  1798.                                          ++j) {
  1799.                                         // Convert each column
  1800.                                         // Note: this is very ineffecient in that it uses
  1801.                                         // ReadPixel().
  1802.                                         // But the cost is fairly small compared to the render time
  1803.                                         if (isHAM6) {
  1804.                                               rr = gg = bb = 0;
  1805.                                            for (i = 0;
  1806.                                                     i < width;
  1807.                                                  ++i) {
  1808.                                                penno = ReadPixel(&Rp,i,j);
  1809.                                                switch (penno & 0x30) {
  1810.                                                case 0:
  1811.                                                    *rx++ = rr = pic->ilbm->RGB[penno*4+1];
  1812.                                                    *gx++ = gg = pic->ilbm->RGB[penno*4+2];
  1813.                                                    *bx++ = bb = pic->ilbm->RGB[penno*4+3];
  1814.                                                    break;
  1815.                                                case 0x10:
  1816.                                                    *rx++ = rr;
  1817.                                                    *gx++ = gg;
  1818.                                                    *bx++ = bb = (penno&0xf)|((penno&0xf)<<4);
  1819.                                                    break;
  1820.                                                case 0x20:
  1821.                                                    *rx++ = rr = (penno&0xf)|((penno&0xf)<<4);
  1822.                                                    *gx++ = gg;
  1823.                                                    *bx++ = bb;
  1824.                                                    break;
  1825.                                                case 0x30:
  1826.                                                    *rx++ = rr;
  1827.                                                    *gx++ = gg = (penno&0xf)|((penno&0xf)<<4);
  1828.                                                    *bx++ = bb;
  1829.                                                    break;
  1830.                                                }
  1831.                                             }
  1832.                                           }
  1833.                                           else {
  1834.                                               if (isHAM8) {
  1835.                                                 rr = gg = bb = 0;
  1836.                                                for (i = 0;
  1837.                                                         i < width;
  1838.                                                      ++i) {
  1839.                                                    penno = ReadPixel(&Rp,i,j);
  1840.                                                    switch (penno & 0xc0) {
  1841.                                                    case 0:
  1842.                                                        *rx++ = rr = pic->ilbm->RGB[penno*4+1];
  1843.                                                        *gx++ = gg = pic->ilbm->RGB[penno*4+2];
  1844.                                                        *bx++ = bb = pic->ilbm->RGB[penno*4+3];
  1845.                                                        break;
  1846.                                                    case 0x40:
  1847.                                                        *rx++ = rr;
  1848.                                                        *gx++ = gg;
  1849.                                                        *bx++ = bb = (penno&0x3f)<<2;
  1850.                                                        break;
  1851.                                                    case 0x80:
  1852.                                                        *rx++ = rr = (penno&0x3f)<<2;
  1853.                                                        *gx++ = gg;
  1854.                                                        *bx++ = bb;
  1855.                                                        break;
  1856.                                                    case 0xc0:
  1857.                                                        *rx++ = rr;
  1858.                                                        *gx++ = gg = (penno&0x3f)<<2;
  1859.                                                        *bx++ = bb;
  1860.                                                        break;
  1861.                                                    }
  1862.                                                 }
  1863.                                               }
  1864.                                               else {
  1865.                                                   if (isEHB) {
  1866.                                                    for (i = 0;
  1867.                                                             i < width;
  1868.                                                          ++i) {
  1869.                                                        penno = ReadPixel(&Rp,i,j);
  1870.                                                        EHB = (penno & 0x20)?1:0;
  1871.                                                        penno &= 0x1f;
  1872.                                                        *rx++ = pic->ilbm->RGB[penno*4+1]>>EHB;
  1873.                                                        *gx++ = pic->ilbm->RGB[penno*4+2]>>EHB;
  1874.                                                        *bx++ = pic->ilbm->RGB[penno*4+3]>>EHB;
  1875.                                                     }
  1876.                                                   }
  1877.                                                   else {
  1878.                                                    for (i = 0;
  1879.                                                             i < width;
  1880.                                                          ++i) {
  1881.                                                        penno = ReadPixel(&Rp,i,j);
  1882.                                                        *rx++ = pic->ilbm->RGB[penno*4+1];
  1883.                                                        *gx++ = pic->ilbm->RGB[penno*4+2];
  1884.                                                        *bx++ = pic->ilbm->RGB[penno*4+3];
  1885.                                                     }
  1886.                                                 }
  1887.                                             }
  1888.                                        }
  1889.                                         rx += ((((width+15)>>4)<<4)-width);
  1890.                                         gx += ((((width+15)>>4)<<4)-width);
  1891.                                         bx += ((((width+15)>>4)<<4)-width);
  1892.                                     }
  1893.                                    AddMessage("Cleaning up");
  1894.                                     unloadbrush(pic->ilbm);
  1895.                                     FreeIFF(pic->ilbm->ParseInfo.iff);
  1896.                                     FreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1897.                                   return TRUE;
  1898.                                }
  1899.                             }
  1900.                         }
  1901.                           if (!e) {
  1902.                          e = "Unable to %s";
  1903.                           e1 = "allocate memory for bitmap";
  1904.                           hnum = H_AllocPlanes;
  1905.                        }
  1906.                     }
  1907.                     if (!e) {
  1908.                        e = "Error loading '%s'";
  1909.                        e1 = filename;
  1910.                        hnum = H_Load;
  1911.                    }
  1912.                     unloadbrush(pic->ilbm);
  1913.                     FreeIFF(pic->ilbm->ParseInfo.iff);
  1914.                 }
  1915.                if (!e) {
  1916.                    e = "Unable to %s";
  1917.                     e1 = "AllocIFF";
  1918.                     hnum = H_AllocIFF;
  1919.                 }
  1920.                 FreeMem(pic->ilbm,sizeof(struct ILBMInfo));
  1921.             }
  1922.             if (!e) {
  1923.                 e = "Unable to '%s'";
  1924.                    e1 = "AllocMem for ILBMInfo";
  1925.                    hnum = H_AllocILBM;
  1926.            }
  1927.        }
  1928.         if (OkFlag && OpalBase) {
  1929.             // If we still have not loaded the image then try opal.library as a last resort
  1930.            AddMessage("Loading using opal.library");
  1931.             Err = LoadImage24(NULL,filename,VIRTUALSCREEN24|FORCE24);
  1932.             if (Err < OL_ERR_MAXERR) {
  1933.                 switch (Err) {
  1934.                 case OL_ERR_OUTOFMEM:
  1935.                     e = "Failure - Out of memory - loading '%s'";
  1936.                     break;
  1937.                 case OL_ERR_OPENFILE:
  1938.                     e = "Failure - Opening file - loading '%s'";
  1939.                     break;
  1940.                 case OL_ERR_FORMATUNKNOWN:
  1941.                     e = "Failure - Unknown Format - loading '%s'";
  1942.                     break;
  1943.                 case OL_ERR_NOTILBM:
  1944.                     e = "Failure - Not an ILBM file - loading '%s'";
  1945.                     break;
  1946.                 case OL_ERR_FILEREAD:
  1947.                     e = "Failure - Reading file - loading '%s'";
  1948.                     break;
  1949.                 case OL_ERR_BADIFF:
  1950.                     e = "Failure - Bad IFF Format - loading '%s'";
  1951.                     break;
  1952.                 case OL_ERR_CANTCLOSE:
  1953.                     e = "Failure - Can not Close - loading '%s'";
  1954.                     break;
  1955.                 case OL_ERR_BADJPEG:
  1956.                     e = "Failure - Bad JPEG Format - loading '%s'";
  1957.                     break;
  1958.                 case OL_ERR_UNSUPPORTED:
  1959.                     e = "Failure - Unsupported Format - loading '%s'";
  1960.                     break;
  1961.                 case OL_ERR_CTRLC:
  1962.                 case OL_ERR_NOTHUMBNAIL:
  1963.                 case OL_ERR_OPENSCREEN:
  1964.                 case OL_ERR_FILEWRITE:
  1965.                 default:
  1966.                     e = "Failure - Unknown problem - loading '%s'";
  1967.                     break;
  1968.                 }
  1969.                 e1 = filename;
  1970.                 hnum = HE_OpalVision;
  1971.             }
  1972.             else {
  1973.                AddMessage("Allocating Bitmaps");
  1974.                 pic->OScrn = (struct OpalScreen *)Err;
  1975.                 // Allocate chunky bit maps
  1976.                 if ((pic->red = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),0)) &&
  1977.                      (pic->green = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),0)) &&
  1978.                      (pic->blue = AllocVec(((((pic->OScrn->Width+15)>>4)<<4)*pic->OScrn->Height),0)) &&
  1979.                            // Allocate temp bit maps if first image and no OpalVision save
  1980.                            ((OVFormat) || (plane0) ||
  1981.                            ((plane0 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1982.                             (plane1 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1983.                             (plane2 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1984.                             (plane3 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1985.                             (plane4 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1986.                             (plane5 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1987.                             (plane6 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP)) &&
  1988.                             (plane7 = AllocVec((((width+15)>>4)<<4),MEMF_CHIP))))) {
  1989.                    AddMessage("Converting Opal to Chunky");
  1990.                      OVtoRGB(pic->OScrn,&(pic->red),0,0,((pic->OScrn->Width+15)>>4)<<4,pic->OScrn->Height);
  1991.                  }
  1992.                  else {
  1993.                  e = "Unable to %s";
  1994.                   e1 = "allocate memory for bitmap";
  1995.                   hnum = H_AllocPlanes;
  1996.                  }
  1997.                 FreeScreen24(pic->OScrn);
  1998.                 if (!e) {
  1999.                     return TRUE;
  2000.                 }
  2001.             }
  2002.         }
  2003.         else {
  2004.             if (!e) {
  2005.                 e = "No opal.library";
  2006.                 hnum = HE_NoOpal;
  2007.             }
  2008.         }
  2009.     }
  2010.     Close24bit(pic);
  2011.     // Display an error message if required
  2012.     if (GUI)
  2013.         Error(e,"Quit",e1,hnum);
  2014.     return(FALSE);
  2015. }
  2016.  
  2017. /* Close an image clearing everything down    */
  2018. void
  2019. Close24bit(struct Picture *pic) {
  2020.     if (pic) {
  2021.         if (pic->rgbonelot) {
  2022.             if (pic->red) {
  2023.                 FreeVec(pic->red);
  2024.             }
  2025.             pic->red = NULL;
  2026.             pic->green = NULL;
  2027.             pic->blue = NULL;
  2028.         }
  2029.         else {
  2030.             if (pic->red) {
  2031.                 FreeVec(pic->red);
  2032.                 pic->red = NULL;
  2033.             }
  2034.             if (pic->green) {
  2035.                 FreeVec(pic->green);
  2036.                 pic->green = NULL;
  2037.             }
  2038.             if (pic->blue) {
  2039.                 FreeVec(pic->blue);
  2040.                 pic->blue = NULL;
  2041.             }
  2042.         }
  2043.     }
  2044. }
  2045.  
  2046. /* Display an error message
  2047.  * ErrorMessage    : The main text
  2048.  * Gadget            : Text for one gadget
  2049.  * extra                : more of the text
  2050.  * helpnum            : Number of a help node
  2051.  *
  2052.  * See the TSMorph source code for more of how this actually works
  2053.  */
  2054. void
  2055. Error(char *ErrorMessage,char *Gadget,char *extra,ULONG helpnum) {
  2056.    struct EasyStruct EasyStruct = {
  2057.       sizeof(struct EasyStruct),
  2058.       0,
  2059.       NULL,
  2060.       NULL,
  2061.       NULL
  2062.    };
  2063.    UBYTE *title = "TSMorph-render Error";
  2064.    struct Window *req;
  2065.    UBYTE gad[32] = "Help|";
  2066.    UBYTE gad1[32] = "_Help|_";
  2067.    ULONG ret = CALL_HANDLER;
  2068.     struct AmigaGuideMsg *agm;
  2069.     ULONG signals;
  2070.     struct rtHandlerInfo *rth;
  2071.     // Disable the window and display the requester
  2072.    DisableWindow();
  2073.    if (ReqToolsBase) {
  2074.        if (!handle) {
  2075.             strcpy(gad1,"_");
  2076.        }
  2077.         strcat(gad1,Gadget);
  2078.         while (ret) {
  2079.             ret = CALL_HANDLER;
  2080.            if (rtEZRequestTags(ErrorMessage,gad1,NULL,&extra,
  2081.                                        RT_ReqHandler, &rth,
  2082.                                        RT_Window, ProgressWnd,
  2083.                                        RT_Underscore, '_',
  2084.                                        RTEZ_ReqTitle, title,
  2085.                                        TAG_END) == CALL_HANDLER) {
  2086.                 while (ret == CALL_HANDLER) {
  2087.                    if (!rth->DoNotWait) {
  2088.                        signals = Wait(rth->WaitMask | ASig);
  2089.                    }
  2090.                     ret = rtReqHandlerA(rth,signals,NULL);
  2091.                    if (ret == 1) {
  2092.                        help(helpnum);
  2093.                    }
  2094.                    if (signals & ASig) {
  2095.                           while (agm = GetAmigaGuideMsg(handle)) {
  2096.                              ReplyAmigaGuideMsg(agm);
  2097.                          }
  2098.                      }
  2099.                 }
  2100.            }
  2101.            else {
  2102.                ret = 0;
  2103.            }
  2104.        }
  2105.    }
  2106.    else {
  2107.         EasyStruct.es_TextFormat = ErrorMessage;
  2108.         EasyStruct.es_Title = title;
  2109.        if (handle) {
  2110.            strcat(gad,Gadget);
  2111.        }
  2112.        else {
  2113.            strcpy(gad,Gadget);
  2114.        }
  2115.         EasyStruct.es_GadgetFormat = gad;
  2116.         req = BuildEasyRequest(ProgressWnd,&EasyStruct,NULL,extra);
  2117.         while (ret) {
  2118.             signals  = Wait((1L << req->UserPort->mp_SigBit) | ASig);
  2119.             if (signals & (1L << req->UserPort->mp_SigBit)) {
  2120.                ret = SysReqHandler(req,NULL,FALSE);
  2121.                if (ret == 1) {
  2122.                    help(helpnum);
  2123.                }
  2124.            }
  2125.            if (signals & ASig) {
  2126.                   while (agm = GetAmigaGuideMsg(handle)) {
  2127.                      ReplyAmigaGuideMsg(agm);
  2128.                  }
  2129.             }
  2130.        }
  2131.        FreeSysRequest(req);
  2132.    }
  2133.    EnableWindow();
  2134. }
  2135.  
  2136. /* Open a file
  2137.  * Returns    : TRUE if ok
  2138.  * filename    : name of file, or NULL for requester
  2139.  */
  2140. BOOL
  2141. MyOpen(char *filename,BOOL JustPoints) {
  2142.     char dirname[257];
  2143.     char *ifilename=NULL;
  2144.     BOOL ok=TRUE;
  2145.     BPTR fh;
  2146.     char buffer[257];
  2147.     LONG w,h;
  2148.     LONG xx,x1,yy,y1;
  2149.     struct FileRequester *filereq;    // For file requester
  2150.     struct MyPoint *MyPoint;
  2151.     // If filename supplied then use it otherwise use file requester
  2152.     if (filename) {
  2153.         ifilename = filename;
  2154.     }
  2155.     else {
  2156.         if (filereq = (struct FileRequest *)AllocFileRequest()) {
  2157.             if (AslRequestTags((APTR) filereq,ASL_Hail,(Tag) "TSMorph-render - Pick project",TAG_DONE)) {
  2158.                 strncpy(dirname,filereq->rf_Dir,256);
  2159.                 if (AddPart(dirname,filereq->rf_File,256)) {
  2160.                     ifilename=dirname;
  2161.                 }
  2162.             }
  2163.          FreeFileRequest(filereq);
  2164.         }
  2165.     }
  2166.     // If user did not cancel
  2167.     if (ifilename) {
  2168.         OpenNewArgs(ifilename);        // Load new parameters
  2169.         // Open file and skip the WB displayable names
  2170.         if (fh=Open(ifilename,MODE_OLDFILE)) {
  2171.             FGets(fh,buffer,256);
  2172.             if (JustPoints && strcmp(buffer,"TSMorph 2.0\n")) {
  2173.                 Error("Invalid file format\nLine '%s'","Quit",buffer,H_FileFormat);
  2174.                 ok = FALSE;
  2175.             }
  2176.             else {
  2177.                 if (!JustPoints) {
  2178.                     Pic1.filename[0]=0;
  2179.                     Pic2.filename[0]=0;
  2180.                     // Keep file name
  2181.                     strcpy(MyFileName,ifilename);
  2182.                     strcat(MyFileName,".%03ld");
  2183.                     if (strcmp(buffer,"TSMorph 1.2\n")) {
  2184.                         Error("Assuming version 1.0 file format","OK",NULL,HE_OldFormat);
  2185.                     }
  2186.                     else {
  2187.                         FGets(fh,buffer,256);
  2188.                     }
  2189.                     if (strlen(buffer)) {
  2190.                         buffer[strlen(buffer)-1]=0;
  2191.                     }
  2192.                     strcpy(Pic1.filename,buffer);
  2193.                     FGets(fh,buffer,256);
  2194.                     if (strlen(buffer)) {
  2195.                         buffer[strlen(buffer)-1]=0;
  2196.                     }
  2197.                     strcpy(Pic2.filename,buffer);
  2198.                     // Get file name, set progress and try and load image
  2199.                     FGets(fh,buffer,256);
  2200.                     if (strlen(buffer)) {
  2201.                         buffer[strlen(buffer)-1]=0;
  2202.                     }
  2203.                     if (buffer[0]) {
  2204.                         strcpy(Pic1.filename,buffer);
  2205.                     }
  2206.                     FGets(fh,buffer,256);
  2207.                     if (strlen(buffer)) {
  2208.                         buffer[strlen(buffer)-1]=0;
  2209.                     }
  2210.                     if (buffer[0]) {
  2211.                         strcpy(Pic2.filename,buffer);
  2212.                     }
  2213.                     // Loaded both so get anim name
  2214.                     FGets(fh,AnimName,256);
  2215.                     if (strlen(AnimName)) {
  2216.                         AnimName[strlen(AnimName)-1]=0;
  2217.                     }
  2218.                     // Read and validate general information
  2219.                     FGets(fh,buffer,256);
  2220.                     if (ok && (sscanf(buffer,"w=%ld,h=%ld,Frames=%ld,Single=%ld,Start=%ld",&w,&h,&Frames,&Single,&Start) != 5)) {
  2221.                         Error("Invalid file format\nLine '%s'","Quit",buffer,H_FileFormat);
  2222.                     }
  2223.                     else {
  2224.                         width = w;        // ???????
  2225.                         height = h;    // ???????
  2226.                         if (ok &&
  2227.                             ((w != width) ||
  2228.                              (h != height))) {
  2229.                             Error("Size does not match image\nLine '%s'","Quit",buffer,H_SizeMatch);
  2230.                             ok = FALSE;
  2231.                         }
  2232.                     }
  2233.                 }
  2234.             }
  2235.             if (ok) {
  2236.                 PointCount = 0;
  2237.                 // Read and store all the points
  2238.                 while (ok &&
  2239.                         FGets(fh,buffer,256) &&
  2240.                         (sscanf(buffer,"x=%ld,y=%ld,x1=%ld,y1=%ld",&xx,&yy,&x1,&y1) == 4)) {
  2241.                     if ((xx<0)||(xx>(width-1)) ||
  2242.                          (yy<0)||(yy>(height-1))) {
  2243.                         Error("Point out of range\nLine '%s'","Quit",buffer,H_Range);
  2244.                         ok = FALSE;
  2245.                     }
  2246.                     if (MyPoint = AllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
  2247.                         MyPoint->x = xx;
  2248.                         MyPoint->y = yy;
  2249.                         MyPoint->x1 = x1;
  2250.                         MyPoint->y1 = y1;
  2251.                         AddTail(&PointList,(struct Node *)MyPoint);
  2252.                         ++PointCount;
  2253.                     }
  2254.                     else {
  2255.                         ok = FALSE;
  2256.                     }
  2257.                 }
  2258.             }
  2259.             if (ok) {    // + 3 should actually be + 1 - but mungwall hits
  2260.                 if (Points = AllocVec((max(PointCount,23) + 3)*sizeof(struct MyPoint *),MEMF_CLEAR)) {
  2261.                 }
  2262.                 else {
  2263.                     Error("Out of memory for points","Quit",NULL,H_MemPointsR);
  2264.                     ok = FALSE;
  2265.                 }
  2266.             }
  2267.             // Close file and cleanup
  2268.             if (!Close(fh)) {
  2269.                 if (ok) {
  2270.                     Error("Error closing file '%s'","Quit",filename,H_CloseFile);
  2271.                     ok = FALSE;
  2272.                 }
  2273.             }
  2274.         }
  2275.         else {
  2276.             Error("Error opening file '%s'","Quit",filename,H_Open);
  2277.             ok = FALSE;
  2278.         }
  2279.     }
  2280.     else {
  2281.         ok = FALSE;
  2282.     }
  2283.     return ok;
  2284. }
  2285.  
  2286. /* Delete all the points from the list    */
  2287. void
  2288. DeleteAllPoints(void) {
  2289.     struct MyPoint *MyPoint;
  2290.     // Loops looking at the head every time and deletes it
  2291.     while ((MyPoint =(struct MyPoint *)PointList.lh_Head)->MyNode.mln_Succ) {
  2292.         Remove((struct Node *)MyPoint);
  2293.         FreeMem(MyPoint,sizeof(struct MyPoint));
  2294.     }
  2295.     if (Points) {
  2296.         FreeVec(Points);
  2297.         Points = NULL;
  2298.     }
  2299. }
  2300.  
  2301. // The following is the alogrithm stuff!!!!!
  2302. // and is not particularly well commented!
  2303.  
  2304. /* Given a point, returns the coordinates in the first and last image    */
  2305. void __regargs
  2306. FindPoint(struct MyPoint *RetPoint) {
  2307.     UWORD KeepCount;
  2308.     struct MyPoint *MyPoint,*MyPoint1,*MyPoint2;
  2309.     struct MyPoint **p,**p1,**p2;
  2310.     UWORD i1,i2;
  2311.     UWORD i,j,k;
  2312.     LONG checkdiff;
  2313.     BOOL flag;
  2314.     for (i = 0;
  2315.           i < (Depth+3);
  2316.           ++i) {
  2317.         Points[i] = &BigPoint;
  2318.     }
  2319.     // Set up differences
  2320.     for (MyPoint = (struct MyPoint *)PointList.lh_Head;
  2321.             MyPoint->MyNode.mln_Succ;
  2322.            MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
  2323.        if (x < MyPoint->Cx) {
  2324.            MyPoint->xdiff = MyPoint->Cx - x;
  2325.        }
  2326.        else {
  2327.            MyPoint->xdiff = x - MyPoint->Cx;
  2328.        }
  2329.        if (y < MyPoint->Cy) {
  2330.            MyPoint->ydiff = MyPoint->Cy - y;
  2331.        }
  2332.        else {
  2333.            MyPoint->ydiff = y - MyPoint->Cy;
  2334.        }
  2335.         if ((MyPoint->xdiff + MyPoint->ydiff) < Points[Depth+2]->Cdiff) {
  2336.            MyPoint->Cdiff = MyPoint->xdiff * MyPoint->xdiff +
  2337.                                   MyPoint->ydiff * MyPoint->ydiff;
  2338.             flag = TRUE;
  2339.             for (i = 0;
  2340.                   flag && (i < (Depth + 3));
  2341.                   ++i) {
  2342.                 if (Points[i]->Cdiff > MyPoint->Cdiff) {
  2343.                     MyPoint1 = Points[i];
  2344.                     Points[i] = MyPoint;
  2345.                     for (j = i+1;
  2346.                           j < (Depth + 3);
  2347.                           ++j) {
  2348.                         MyPoint2 = Points[j];
  2349.                         Points[j] = MyPoint1;
  2350.                         MyPoint1 = MyPoint2;
  2351.                     }
  2352.                     flag = FALSE;
  2353.                 }
  2354.             }
  2355.         }
  2356.     }
  2357.    // If on an actual point then easy
  2358.    if (!Points[0]->Cdiff) {
  2359.        if (AntiAlias) {
  2360.             RetPoint->xd = Points[0]->x;
  2361.             RetPoint->x1d = Points[0]->x1;
  2362.             RetPoint->yd = Points[0]->y;
  2363.             RetPoint->y1d = Points[0]->y1;
  2364.        }
  2365.        else {
  2366.             RetPoint->x = Points[0]->x;
  2367.             RetPoint->x1 = Points[0]->x1;
  2368.             RetPoint->y = Points[0]->y;
  2369.             RetPoint->y1 = Points[0]->y1;
  2370.         }
  2371.         return;
  2372.    }
  2373.    // otherwise try and find a triangle with the other points
  2374.       KeepCount = 0;
  2375.       if (Mode & MODE_CLOSEST) {
  2376.         checkdiff = 0x7FFFFFFF;
  2377.         for (p = Points, i=0;
  2378.               i<(Depth+1);
  2379.               ++i,++p) {
  2380.             if ((*p)->Cdiff < checkdiff) {
  2381.                 for (p1 = p+1, j=i;
  2382.                       j<(Depth+1);
  2383.                       ++j,++p1) {
  2384.                     if (((*p)->Cdiff + (*p1)->Cdiff) < checkdiff) {
  2385.                         i1 = intersect(*p,*p1);
  2386.                         for (p2 = p1+1, k=j;
  2387.                               k<(Depth+1);
  2388.                               ++k,++p2) {
  2389.                             // loop thru 3 point combinations finding smallest triangle
  2390.                             if (((*p)->Cdiff + (*p1)->Cdiff + (*p2)->Cdiff) < checkdiff) {
  2391.                                if (i1 + (i2 = intersect(*p1,*p2)) < 2) {
  2392.                                    if ((i1 + i2 + intersect(*p2,*p)) == 1) {
  2393.                                        KeepCount = 1;
  2394.                                        MyPoint = *p;
  2395.                                         MyPoint1 = *p1;
  2396.                                         MyPoint2 = *p2;
  2397.                                         checkdiff = (*p)->Cdiff + (*p1)->Cdiff + (*p2)->Cdiff;
  2398.                                     }
  2399.                                 }
  2400.                             }
  2401.                        }
  2402.                    }
  2403.                }
  2404.            }
  2405.           }
  2406.       }
  2407.       else {
  2408.         for (p = Points, i=0;
  2409.               !KeepCount && (i<(Depth+1));
  2410.               ++i,++p) {
  2411.             for (p1 = p+1, j=i;
  2412.                   !KeepCount && (j<(Depth+1));
  2413.                   ++j,++p1) {
  2414.                 i1 = intersect(*p,*p1);
  2415.                 for (p2 = p1+1, k=j;
  2416.                       !KeepCount && (k<(Depth+1));
  2417.                       ++k,++p2) {
  2418.                     // loop thru 3 point combinations finding smallest triangle
  2419.                    if (i1 + (i2 = intersect(*p1,*p2)) < 2) {
  2420.                        if ((i1 + i2 + intersect(*p2,*p)) == 1) {
  2421.                            MyPoint = *p;
  2422.                            MyPoint1 = *p1;
  2423.                            MyPoint2 = *p2;
  2424.                            KeepCount = 1;
  2425.                        }
  2426.                    }
  2427.                }
  2428.            }
  2429.           }
  2430.     }
  2431.       // If still no triangle then assume stationary
  2432.       if (!KeepCount && (Mode & MODE_STAT)) {
  2433.        if (AntiAlias) {
  2434.             RetPoint->xd = x;
  2435.             RetPoint->x1d = x;
  2436.             RetPoint->yd = y;
  2437.             RetPoint->y1d = y;
  2438.        }
  2439.        else {
  2440.               RetPoint->x = x;
  2441.               RetPoint->y = y;
  2442.               RetPoint->x1 = x;
  2443.               RetPoint->y1 = y;
  2444.           }
  2445.           return;
  2446.       }
  2447.       if (!KeepCount) {
  2448.           MyPoint = Points[0];
  2449.           MyPoint1 = Points[1];
  2450.           MyPoint2 = Points[2];
  2451.       }
  2452.     // Otherwise do the triangle calculation
  2453.       Triangle(RetPoint,MyPoint,MyPoint1,MyPoint2);
  2454.    // Check the point is actually on the image
  2455.       if (AntiAlias) {
  2456.        if (RetPoint->xd < 0) {
  2457.            RetPoint->xd = 0;
  2458.        }
  2459.        if (RetPoint->yd < 0) {
  2460.            RetPoint->yd = 0;
  2461.        }
  2462.        if (RetPoint->x1d < 0) {
  2463.            RetPoint->x1d = 0;
  2464.        }
  2465.        if (RetPoint->y1d < 0) {
  2466.            RetPoint->y1d = 0;
  2467.        }
  2468.        if (RetPoint->xd > (width-1)) {
  2469.            RetPoint->xd = width-1;
  2470.        }
  2471.        if (RetPoint->yd > (height-1)) {
  2472.            RetPoint->yd = height-1;
  2473.        }
  2474.        if (RetPoint->x1d > (width-1)) {
  2475.            RetPoint->x1d = width-1;
  2476.        }
  2477.        if (RetPoint->y1d > (height-1)) {
  2478.            RetPoint->y1d = height-1;
  2479.        }
  2480.       }
  2481.       else {
  2482.        if (RetPoint->x < 0) {
  2483.            RetPoint->x = 0;
  2484.        }
  2485.        if (RetPoint->y < 0) {
  2486.            RetPoint->y = 0;
  2487.        }
  2488.        if (RetPoint->x1 < 0) {
  2489.            RetPoint->x1 = 0;
  2490.        }
  2491.        if (RetPoint->y1 < 0) {
  2492.            RetPoint->y1 = 0;
  2493.        }
  2494.        if (RetPoint->x > (width-1)) {
  2495.            RetPoint->x = width-1;
  2496.        }
  2497.        if (RetPoint->y > (height-1)) {
  2498.            RetPoint->y = height-1;
  2499.        }
  2500.        if (RetPoint->x1 > (width-1)) {
  2501.            RetPoint->x1 = width-1;
  2502.        }
  2503.        if (RetPoint->y1 > (height-1)) {
  2504.            RetPoint->y1 = height-1;
  2505.        }
  2506.     }
  2507. }
  2508.  
  2509. /* Used to determine if a point lies on a line,
  2510.  * or in triangle of 3 points
  2511.  */
  2512. UWORD __regargs
  2513. intersect(struct MyPoint *Pointa,struct MyPoint *Pointb) {
  2514. // Draws line between a and b and sees if line from x,0 to x,y intersects
  2515. // returns 1 if intersects, 0 if not intersect
  2516.     if (Pointb->Cx == Pointa->Cx) {                                // Vertical a to b
  2517.         if ((Pointb->x == x) &&                                        // x,y on a to b
  2518.              (((Pointb->Cy > y) && (Pointa->Cy < y)) ||
  2519.               ((Pointb->Cy < y) && (Pointa->Cy > y)))) {
  2520.             return 1;                                                    // Beteen a and b
  2521.         }
  2522.         return 0;
  2523.     }
  2524.     if (((Pointb->Cy > y) && (Pointa->Cy > y)) ||
  2525.          ((Pointb->Cx > x) && (Pointa->Cx > x)) ||
  2526.          ((Pointb->Cx < x) && (Pointa->Cx < x))) {        // Can not possibly cross 
  2527.         return 0;
  2528.     }
  2529.     if ((Pointb->Cy < y) && (Pointa->Cy < y)) {
  2530.         return 1;
  2531.     }
  2532.     if (Pointa->Cx == x) {
  2533.         if (Pointa->Cy > y) {
  2534.             return 0;
  2535.         }
  2536.         return 1;
  2537.     }
  2538.     if (Pointb->Cx == x) {
  2539.         if (Pointb->Cy > y) {
  2540.             return 0;
  2541.         }
  2542.         return 1;
  2543.     }
  2544.     if (Pointb->Cy == Pointa->Cy) {
  2545.         if (Pointa->Cy > y) {
  2546.             return 0;
  2547.         }
  2548.         return 1;
  2549.     }
  2550.     if ((((Pointa->Cx < x)?(x - Pointa->Cx):(Pointa->Cx - x)) * Pointb->Cy +
  2551.           ((Pointb->Cx < x)?(x - Pointb->Cx):(Pointb->Cx - x)) * Pointa->Cy) /
  2552.           ((Pointb->Cx < Pointa->Cx)?(Pointa->Cx - Pointb->Cx):(Pointb->Cx - Pointa->Cx)) > y) {
  2553.         return 0;
  2554.     }
  2555.     return 1;
  2556. }
  2557.  
  2558. /* Given 3 points (a,b,c) with a point (p) in the triangle
  2559.  * determine the coordinates of point (p) on the first and last frame
  2560.  */
  2561. void __regargs
  2562. Triangle(struct MyPoint *p,struct MyPoint *a,struct MyPoint *bb,struct MyPoint *c) {
  2563.     double AB1,AB2,BC1,BC2,CA1,CA2;
  2564.     double AB,BC,CA;
  2565.     double ABBCCA2;
  2566.     double ABCA,BCCA,ABBC;
  2567.     double BC1BC2,AB1AB2,CA1CA2;
  2568.     CalcDiffs(a,bb,&AB1,&AB2,&AB);
  2569.     CalcDiffs(bb,c,&BC1,&BC2,&BC);
  2570.     CalcDiffs(c,a,&CA1,&CA2,&CA);
  2571.     ABBCCA2 = 2 * (AB + BC + CA);
  2572.     ABCA = AB+CA;
  2573.     BCCA = BC+CA;
  2574.     ABBC = AB+BC;
  2575.     BC1BC2 = BC1+BC2;
  2576.     AB1AB2 = AB1+AB2;
  2577.     CA1CA2 = CA1+CA2;
  2578.     if (AntiAlias) {
  2579.         p->xd = x +
  2580.                     (ABCA*(BC1*(c->x - c->Cx) + BC2*(bb->x - bb->Cx)) / BC1BC2 +
  2581.                      BCCA*(AB1*(bb->x - bb->Cx) + AB2*(a->x - a->Cx)) / AB1AB2 +
  2582.                      ABBC*(CA1*(a->x - a->Cx) + CA2*(c->x - c->Cx)) / CA1CA2) /
  2583.                     ABBCCA2;
  2584.         p->x1d = x +
  2585.                     (ABCA*(BC1*(c->x1 - c->Cx) + BC2*(bb->x1 - bb->Cx)) / BC1BC2 +
  2586.                      BCCA*(AB1*(bb->x1 - bb->Cx) + AB2*(a->x1 - a->Cx)) / AB1AB2 +
  2587.                      ABBC*(CA1*(a->x1 - a->Cx) + CA2*(c->x1 - c->Cx)) / CA1CA2) /
  2588.                     ABBCCA2;
  2589.         p->y1d = y +
  2590.                     (ABCA*(BC1*(c->y1 - c->Cy) + BC2*(bb->y1 - bb->Cy)) / BC1BC2 +
  2591.                      BCCA*(AB1*(bb->y1 - bb->Cy) + AB2*(a->y1 - a->Cy)) / AB1AB2 +
  2592.                      ABBC*(CA1*(a->y1 - a->Cy) + CA2*(c->y1 - c->Cy)) / CA1CA2) /
  2593.                     ABBCCA2;
  2594.         p->yd = y +
  2595.                     (ABCA*(BC1*(c->y - c->Cy) + BC2*(bb->y - bb->Cy)) / BC1BC2 +
  2596.                      BCCA*(AB1*(bb->y - bb->Cy) + AB2*(a->y - a->Cy)) / AB1AB2 +
  2597.                      ABBC*(CA1*(a->y - a->Cy) + CA2*(c->y - c->Cy)) / CA1CA2) /
  2598.                     ABBCCA2;
  2599.     }
  2600.     else {
  2601.         p->x = x +
  2602.                     (ABCA*(BC1*(c->x - c->Cx) + BC2*(bb->x - bb->Cx)) / BC1BC2 +
  2603.                      BCCA*(AB1*(bb->x - bb->Cx) + AB2*(a->x - a->Cx)) / AB1AB2 +
  2604.                      ABBC*(CA1*(a->x - a->Cx) + CA2*(c->x - c->Cx)) / CA1CA2) /
  2605.                     ABBCCA2;
  2606.         p->x1 = x +
  2607.                     (ABCA*(BC1*(c->x1 - c->Cx) + BC2*(bb->x1 - bb->Cx)) / BC1BC2 +
  2608.                      BCCA*(AB1*(bb->x1 - bb->Cx) + AB2*(a->x1 - a->Cx)) / AB1AB2 +
  2609.                      ABBC*(CA1*(a->x1 - a->Cx) + CA2*(c->x1 - c->Cx)) / CA1CA2) /
  2610.                     ABBCCA2;
  2611.         p->y1 = y +
  2612.                     (ABCA*(BC1*(c->y1 - c->Cy) + BC2*(bb->y1 - bb->Cy)) / BC1BC2 +
  2613.                      BCCA*(AB1*(bb->y1 - bb->Cy) + AB2*(a->y1 - a->Cy)) / AB1AB2 +
  2614.                      ABBC*(CA1*(a->y1 - a->Cy) + CA2*(c->y1 - c->Cy)) / CA1CA2) /
  2615.                     ABBCCA2;
  2616.         p->y = y +
  2617.                     (ABCA*(BC1*(c->y - c->Cy) + BC2*(bb->y - bb->Cy)) / BC1BC2 +
  2618.                      BCCA*(AB1*(bb->y - bb->Cy) + AB2*(a->y - a->Cy)) / AB1AB2 +
  2619.                      ABBC*(CA1*(a->y - a->Cy) + CA2*(c->y - c->Cy)) / CA1CA2) /
  2620.                     ABBCCA2;
  2621.     }
  2622. }
  2623.  
  2624. /* Caclulate the distances between various points    */
  2625. void __regargs
  2626. CalcDiffs(struct MyPoint *a,struct MyPoint *bb,double *ab1,double *ab2,double *ab) {
  2627.     // ab is length x,y to line ab
  2628.     // ab1 is length x,y to intersect of ab
  2629.     // ab2 is length intersect of ab to bb
  2630.     double m;
  2631.     double c;        // y = mx+c line a to bb
  2632.     double n;
  2633.     double d;        // y = nx+d line perp to y=mx+c thru x,y
  2634.     double xsolve,ysolve;
  2635.     if (a->Cx == bb->Cx) {
  2636.         *ab  = a->xdiff;
  2637.         *ab1 = a->ydiff;
  2638.         *ab2 = bb->ydiff;
  2639.     }
  2640.     else {
  2641.         if (a->Cy == bb->Cy) {
  2642.             *ab1 = a->xdiff;
  2643.             *ab2 = bb->xdiff;
  2644.             *ab  = a->ydiff;
  2645.         }
  2646.         else {
  2647.             m = (double)(bb->Cy - a->Cy) / (double)(bb->Cx - a->Cx);
  2648.             c = bb->Cy - (bb->Cx * m);
  2649.             n = (-1) / m;
  2650.             d = y - n * x;
  2651.             xsolve = (d - c)/(m - n);
  2652.             ysolve = m * xsolve + c;
  2653.             *ab1 = sqrt(((a->Cy - ysolve) * (a->Cy - ysolve) + (a->Cx - xsolve) * (a->Cx - xsolve)));
  2654.             *ab2 = sqrt(((bb->Cy - ysolve) * (bb->Cy - ysolve) + (bb->Cx - xsolve) * (bb->Cx - xsolve)));
  2655.             *ab  = sqrt(((y - ysolve) * (y - ysolve) + (x - xsolve) * (x - xsolve)));
  2656.         }
  2657.     }
  2658. }
  2659.  
  2660. /* Frame clicked - irrelevant    */
  2661. int
  2662. FrameClicked(void) {
  2663.     return 1;
  2664. }
  2665.  
  2666.  
  2667. /* Line clicked - irrelevant    */
  2668. int
  2669. LineClicked(void) {
  2670.     return 1;
  2671. }
  2672.  
  2673. /* Routine for when Stop clicked    */
  2674. int
  2675. StopClicked(void) {
  2676.    struct EasyStruct EasyStruct = {
  2677.       sizeof(struct EasyStruct),
  2678.       0,
  2679.       NULL,
  2680.       NULL,
  2681.       NULL,
  2682.    };
  2683.     UBYTE *title = "TSMorph-render";
  2684.     UBYTE *body = "Really quit?";
  2685.    struct Window *req;
  2686.    UBYTE *gad;
  2687.    ULONG ret = 2;
  2688.     struct AmigaGuideMsg *agm;
  2689.     ULONG signals;
  2690.     struct rtHandlerInfo *rth;
  2691.    // Disable the window, display a requester and reenable the window
  2692.    DisableWindow();
  2693.    if (ReqToolsBase) {
  2694.        if (handle) {
  2695.             gad = "_Quit|_Help|_Continue";
  2696.        }
  2697.        else {
  2698.             gad = "_Quit|_Continue";
  2699.        }
  2700.         while (ret == 2) {
  2701.             ret = CALL_HANDLER;
  2702.            if (rtEZRequestTags(body,gad,NULL,NULL,
  2703.                                        RT_ReqHandler, &rth,
  2704.                                        RT_Window, ProgressWnd,
  2705.                                        RT_Underscore, '_',
  2706.                                        RTEZ_ReqTitle, title,
  2707.                                        TAG_END) == CALL_HANDLER) {
  2708.                 while (ret == CALL_HANDLER) {
  2709.                    if (!rth->DoNotWait) {
  2710.                        signals = Wait(rth->WaitMask | ASig);
  2711.                    }
  2712.                     ret = rtReqHandlerA(rth,signals,NULL);
  2713.                    if (ret == 2) {
  2714.                        help(H_Really);
  2715.                    }
  2716.                    if (signals & ASig) {
  2717.                           while (agm = GetAmigaGuideMsg(handle)) {
  2718.                              ReplyAmigaGuideMsg(agm);
  2719.                          }
  2720.                      }
  2721.                 }
  2722.            }
  2723.            else {
  2724.                ret = 0;
  2725.            }
  2726.        }
  2727.     }
  2728.     else {
  2729.         EasyStruct.es_TextFormat = body;
  2730.         EasyStruct.es_Title = title;
  2731.        if (handle) {
  2732.            EasyStruct.es_GadgetFormat = "Quit|Help|Continue";
  2733.        }
  2734.        else {
  2735.            EasyStruct.es_GadgetFormat = "Quit|Continue";
  2736.        }
  2737.         req = BuildEasyRequest(ProgressWnd,&EasyStruct,NULL,NULL);
  2738.        while ((ret = SysReqHandler(req,NULL,TRUE)) == 2) {
  2739.            help(H_Really);
  2740.               while (agm = GetAmigaGuideMsg(handle)) {
  2741.                  ReplyAmigaGuideMsg(agm);
  2742.              }
  2743.        }
  2744.        FreeSysRequest(req);
  2745.    }
  2746.    EnableWindow();
  2747.     return !ret;
  2748. }
  2749.  
  2750. /* Disables the Progress window
  2751.  * Disables the 'Stop' gadget and displays a wait pointer
  2752.  */
  2753. void
  2754. DisableWindow(void) {
  2755.     if (ProgressWnd) {
  2756.         GT_SetGadgetAttrs(ProgressGadgets[GDX_Stop],ProgressWnd,NULL,GA_Disabled,TRUE,TAG_END);
  2757.         SetPointer(ProgressWnd, BusyPointerData, 16, 16, -6, 0);
  2758.     }
  2759. }
  2760.  
  2761. /* Enables the Progress window
  2762.  * Enables the 'Stop' gadget and clears the pointer
  2763.  */
  2764. void
  2765. EnableWindow(void) {
  2766.     if (ProgressWnd) {
  2767.         GT_SetGadgetAttrs(ProgressGadgets[GDX_Stop],ProgressWnd,NULL,GA_Disabled,FALSE,TAG_END);
  2768.         ClearPointer(ProgressWnd);
  2769.     }
  2770. }
  2771.  
  2772. /* Tries to execute a Rexx script
  2773.  * msgtxt = name of script
  2774.  * IgnoreError = TRUE then do not display error message
  2775.  * Returns:    error message
  2776.  */
  2777. LONG
  2778. SendRxMsg(char *msgtxt,BOOL IgnoreError) {
  2779.     struct MsgPort *reply_port;
  2780.     struct MsgPort *rx_port;
  2781.     struct RexxMsg *rx_msg;
  2782.     LONG                 ret             = RC_FATAL;
  2783.  
  2784.     if (reply_port = CreateMsgPort()) {
  2785.        if (rx_msg = CreateRexxMsg(reply_port,"TSM","REXX")) {
  2786.           rx_msg->rm_Args[0] = msgtxt;
  2787.             if (FillRexxMsg(rx_msg,1,0)) {
  2788.                 rx_msg->rm_Action = RXCOMM;
  2789.                 Forbid();
  2790.                 if (rx_port = (struct MsgPort *)FindPort("REXX")) {
  2791.                   PutMsg(rx_port, (struct Message *)rx_msg);
  2792.                   Permit();
  2793.                   WaitPort(reply_port);
  2794.                   ReplyMsg(GetMsg(reply_port));
  2795.                   ret = rx_msg->rm_Result1;
  2796.                  }
  2797.                 else {
  2798.                   Permit();
  2799.                 }
  2800.                 ClearRexxMsg(rx_msg, 1);
  2801.           }
  2802.              DeleteRexxMsg(rx_msg);
  2803.         }
  2804.         DeleteMsgPort(reply_port);
  2805.       }
  2806.     // Display an error message (if required)
  2807.       if (!IgnoreError && ret) {
  2808.           Error("Error sending ARexx message\n'%s'","Quit",msgtxt,H_ARexx);
  2809.       }
  2810.       return ret;
  2811. }
  2812.  
  2813. /* Handle 'Help' key    */
  2814. int
  2815. ProgressRawKey(void) {
  2816.     switch (ProgressMsg.Code) {
  2817.     case 0x5f:
  2818.         help(H_Help);
  2819.     }
  2820.     return 1;
  2821. }
  2822.  
  2823. // Load some image(s) for a frame
  2824. BOOL
  2825. LoadFrames(BOOL points,BOOL image1,BOOL image2) {
  2826.     char buffer[257];
  2827.     BOOL ok=TRUE;
  2828.     if ((Single == 2) || (Single == 3)) {
  2829.         if (points) {
  2830.             AddMessage("Loading points");
  2831.             DeleteAllPoints();
  2832.             sprintf(buffer,MyFileName,f+Start-1);
  2833.             ok = MyOpen(buffer,TRUE);
  2834.         }
  2835.         sprintf(buffer,Pic1.filename,f+Start-1);
  2836.     }
  2837.     else {
  2838.         strcpy(buffer,Pic1.filename);
  2839.     }
  2840.     if (ok) {
  2841.         if (image1) {
  2842.             ok = Pic1_Open = Load24bit(buffer,&Pic1,TRUE);
  2843.         }
  2844.         if (image2 && ok && ((Single == 0) || (Single == 2))) {
  2845.             // If we loaded the 1st image then try the second
  2846.             if (Single == 2) {
  2847.                 sprintf(buffer,Pic2.filename,f+Start-1);
  2848.             }
  2849.             else {
  2850.                 strcpy(buffer,Pic2.filename);
  2851.             }
  2852.             ok = Pic2_Open = Load24bit(buffer,&Pic2,TRUE);
  2853.         }
  2854.     }
  2855.     return ok;
  2856. }
  2857.  
  2858. static UWORD top = 0;
  2859.  
  2860. // add a message to the progress list
  2861. void
  2862. AddMessage(UBYTE *message) {
  2863.     struct Node *node;
  2864.     if ((node = (struct Node *)malloc(sizeof(struct Node))) &&
  2865.          (node->ln_Name = strdup(message))) {;
  2866.         GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
  2867.                              GTLV_Labels, ~0,
  2868.                             TAG_END);
  2869.         AddTail(&InfoList,node);
  2870.         GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
  2871.                              GTLV_Labels, &InfoList,
  2872.                              GTLV_Top, top,
  2873.                             TAG_END);
  2874.           top++;
  2875.     }
  2876. }
  2877.